capistrano-sbt 0.0.7 → 0.1.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.
data/README.md CHANGED
@@ -26,29 +26,29 @@ This recipes will try to do following things during Capistrano `deploy:setup` an
26
26
 
27
27
  To build you sbt projects during Capistrano `deploy` tasks, add following in you `config/deploy.rb`. By default, sbt build will run after the Capistrano's `deploy:finalize_update`.
28
28
 
29
- # in "config/deploy.rb"
30
- require 'capistrano-sbt'
31
- set(:sbt_version, '0.11.2') # sbt version to build project
29
+ # config/deploy.rb
30
+ require "capistrano-sbt"
32
31
 
33
32
  Following options are available to manage your sbt build.
34
33
 
35
- * `:sbt_use_extras` - Use [sbt-extras](https://github.com/paulp/sbt-extras) to manage sbt. `false` by default.
36
- * `:sbt_version` - Project sbt version. This value may be discarded if `sbt_use_extras` is turned `true`.
37
- * `:sbt_archive_url` - Download URL for specified sbt version. This value may be discarded if `sbt_use_extras` is turned `true`.
38
- * `:sbt_compile_locally` - compile project on localhost. false by default.
39
- * `:sbt_goals` - sbt commands and tasks to execute. default is "reload clean package".
40
- * `:sbt_update_settings` - update `*.sbt` or not. false by default.
41
- * `:sbt_update_settings_locally` - udate `*.sbt` or not on local compilation. false by default.
42
- * `:sbt_settings` - list of your optional `*.sbt` files
43
- * `:sbt_settings_local` - list of your optional `*.sbt` files in on local compilation.
44
- * `:sbt_settings_path` - the destination path of the optional `*.sbt` files.
45
- * `:sbt_settings_path_local` - the destination path of the optional `*.sbt` files.
46
- * `:sbt_template_path` - specify ERB template path for `*.sbt`.
47
- * `:sbt_java_home` - optional `JAVA_HOME` settings for sbt commands.
48
- * `:sbt_java_home_local` - optional `JAVA_HOME` settings for sbt commands in localhost.
49
- * `:sbt_extras_url` - Download URL of `sbt` script of sbt-extras.
50
- * `:sbt_extras_check_interval` - Check updates of sbt-extras every specified seconds. `86400` by default.
51
- * `:sbt_log_noformat` - Do not colorize sbt outputs. `true` by default.
34
+ * `:sbt_use_extras` - Use [sbt-extras](https://github.com/paulp/sbt-extras) to manage sbt. `true` by default.
35
+ * `:sbt_extras_url` - The download url of sbt-extras.
36
+ * `:sbt_version` - If `:sbt_use_extras` was set as `false`, download specified version of `sbt-launch.jar` and set it up as `sbt`. If no version was given, try loading version from `project/build.properties`.
37
+ * `:sbt_setup_remotely` - Setup `sbt` on remote servers. As same value as `:sbt_update_remotely` by default.
38
+ * `:sbt_setup_locally` - Setup `sbt` on local server. Asa same value as `:sbt_update_locally` by default.
39
+ * `:sbt_update_remotely` - Run `sbt` on remote servers. `true` by default.
40
+ * `:sbt_update_locally` - Run `sbt` on local server. `false` by default.
41
+ * `:sbt_goals` - The `sbt` commands and tasks to be be executed. Run `reload clean package` by default.
42
+ * `:sbt_project_path` - The project path to be built on remote servers.
43
+ * `:sbt_project_path_local` - The project path to be built on local server.
44
+ * `:sbt_settings` - List of optional `*.sbt` files for remote servers.
45
+ * `:sbt_settings_local` - List of optional `*.sbt` files for local server.
46
+ * `:sbt_template_path` - The local path where the templates of `*.sbt` are in. By default, searches from `config/templates`.
47
+ * `:sbt_settings_path` - The destination path of the optional `*.sbt` files.
48
+ * `:sbt_settings_path_local` - The destination path of the optional `*.sbt` files.
49
+ * `:sbt_java_home` - Optional `JAVA_HOME` settings for `sbt` on remote servers.
50
+ * `:sbt_java_home_local` - Optional `JAVA_HOME` settings for `sbt` on local server.
51
+ * `:sbt_log_noformat` - Do not colorize `sbt` outputs. `true` by default.
52
52
  * `:sbt_release_build` - Skip building on SNAPSHOT version. `false` by default.
53
53
 
54
54
  ## Contributing
@@ -13,9 +13,13 @@ Gem::Specification.new do |gem|
13
13
  gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
14
14
  gem.name = "capistrano-sbt"
15
15
  gem.require_paths = ["lib"]
16
- gem.version = Capistrano::Sbt::VERSION
16
+ gem.version = Capistrano::SBT::VERSION
17
17
 
18
18
  gem.add_dependency("capistrano")
19
- gem.add_dependency("capistrano-file-resources", "~> 0.0.1")
20
- gem.add_dependency("capistrano-file-transfer-ext", "~> 0.0.3")
19
+ gem.add_dependency("capistrano-file-resources", "~> 0.1.0")
20
+ gem.add_dependency("capistrano-file-transfer-ext", "~> 0.1.0")
21
+ gem.add_development_dependency("capistrano-jdk-installer", "~> 0.1.0")
22
+ gem.add_development_dependency("net-scp", "~> 1.0.4")
23
+ gem.add_development_dependency("net-ssh", "~> 2.2.2")
24
+ gem.add_development_dependency("vagrant", "~> 1.0.6")
21
25
  end
@@ -2,267 +2,480 @@ require "capistrano-sbt/version"
2
2
  require "capistrano"
3
3
  require "capistrano/configuration/actions/file_transfer_ext"
4
4
  require "capistrano/configuration/resources/file_resources"
5
+ require "tempfile"
5
6
  require "uri"
6
7
 
7
8
  module Capistrano
8
- module Sbt
9
+ module SBT
9
10
  def self.extended(configuration)
10
11
  configuration.load {
11
12
  namespace(:sbt) {
12
- _cset(:sbt_version, '0.12.2')
13
- _cset(:sbt_group_id) {
14
- case sbt_version
15
- when /^0\.(?:7|10)\.\d+$/, /^0\.11\.[0-2]$/
16
- 'org.scala-tools.sbt'
13
+ _cset(:sbt_roles, [:app])
14
+ _cset(:sbt_tools_path) { File.join(shared_path, "tools", "sbt") }
15
+ _cset(:sbt_tools_path_local) { File.expand_path("tools/sbt") }
16
+ _cset(:sbt_archive_path) { sbt_tools_path }
17
+ _cset(:sbt_archive_path_local) { sbt_tools_path_local }
18
+ _cset(:sbt_path) {
19
+ if sbt_use_extras
20
+ File.join(sbt_tools_path, "sbt-extras")
17
21
  else
18
- 'org.scala-sbt'
22
+ File.join(sbt_tools_path, "sbt-#{sbt_version}")
19
23
  end
20
24
  }
21
- _cset(:sbt_jar_url) {
22
- "http://typesafe.artifactoryonline.com/typesafe/ivy-releases/#{sbt_group_id}/sbt-launch/#{sbt_version}/sbt-launch.jar"
23
- }
24
- _cset(:sbt_jar_file) {
25
- File.join(shared_path, 'tools', 'sbt', "sbt-#{sbt_version}", File.basename(URI.parse(sbt_jar_url).path))
26
- }
27
- _cset(:sbt_jar_file_local) {
28
- File.join(File.expand_path('.'), 'tools', 'sbt', "sbt-#{sbt_version}", File.basename(URI.parse(sbt_jar_url).path))
25
+ _cset(:sbt_path_local) {
26
+ if sbt_use_extras
27
+ File.join(sbt_tools_path_local, "sbt-extras")
28
+ else
29
+ File.join(sbt_tools_path_local, "sbt-#{sbt_version}")
30
+ end
29
31
  }
30
- _cset(:sbt_use_extras, false)
32
+ _cset(:sbt_bin_path) { sbt_path }
33
+ _cset(:sbt_bin_path_local) { sbt_path_local }
34
+ _cset(:sbt_bin) { File.join(sbt_bin_path, "sbt") }
35
+ _cset(:sbt_bin_local) { File.join(sbt_bin_path_local, "sbt") }
36
+ _cset(:sbt_project_path) { release_path }
37
+ _cset(:sbt_project_path_local) { File.expand_path(".") }
38
+ _cset(:sbt_target_path) { File.join(sbt_project_path, "target") }
39
+ _cset(:sbt_target_path_local) { File.join(sbt_project_path_local, "target") }
40
+ _cset(:sbt_template_path) { File.expand_path("config/templates") }
41
+
42
+ ## sbt-extras
43
+ _cset(:sbt_use_extras, true)
31
44
  _cset(:sbt_extras_url, "https://raw.github.com/paulp/sbt-extras/master/sbt")
32
- _cset(:sbt_extras_file) { File.join(shared_path, 'tools', 'sbt', 'sbt') }
33
- _cset(:sbt_extras_file_local) { File.join(File.expand_path('.'), 'tools', 'sbt', 'sbt') }
34
- _cset(:sbt_extras_check_interval, 86400)
35
- _cset(:sbt_extras_check_timestamp) { (Time.now - sbt_extras_check_interval).strftime('%Y%m%d%H%M') }
36
- _cset(:sbt_cmd) {
37
- if fetch(:sbt_java_home, nil)
38
- env = "env JAVA_HOME=#{sbt_java_home.dump}"
39
- java = "#{sbt_java_home}/bin/java"
45
+ _cset(:sbt_extras_file) { File.join(sbt_tools_path, "sbt") }
46
+ _cset(:sbt_extras_file_local) { File.join(sbt_tools_path_local, "sbt") }
47
+ _cset(:sbt_extras_update_interval) {
48
+ if exists?(:sbt_extras_check_interval)
49
+ logger.info(":sbt_extras_check_interval has been deprecated. use :sbt_extras_update_interval instead.")
50
+ fetch(:sbt_extras_check_interval)
40
51
  else
41
- env = ""
42
- java = "java"
52
+ 86400
43
53
  end
44
- if sbt_use_extras
45
- "#{env} #{sbt_extras_file} #{sbt_options.join(' ')}".strip
54
+ }
55
+ _cset(:sbt_extras_update_timestamp) { (Time.now - sbt_extras_update_interval).strftime("%Y%m%d%H%M") }
56
+
57
+ ## sbt-launch.jar
58
+ _cset(:sbt_project_sbt_version) {
59
+ begin
60
+ tempfile = Tempfile.new("capistrano-sbt")
61
+ download(File.join(sbt_project_path, "project", "build.properties"), tempfile.path)
62
+ tempfile.rewind()
63
+ tempfile.read().scan(/^sbt\.version=(.*)$/).map { |x| x.last }.last
64
+ rescue
65
+ nil
66
+ ensure
67
+ tempfile.close()
68
+ end
69
+ }
70
+ _cset(:sbt_project_sbt_version_local) {
71
+ begin
72
+ properties = File.read(File.join(sbt_project_path_local, "project", "build.properties"))
73
+ properties.scan(/^sbt\.version=(.*)$/).map { |x| x.last }.last
74
+ rescue
75
+ nil
76
+ end
77
+ }
78
+ _cset(:sbt_version) {
79
+ version ||= sbt_project_sbt_version if sbt_update_remotely
80
+ version ||= sbt_project_sbt_version_local if sbt_update_locally
81
+ version ||= "0.12.2"
82
+ logger.debug("Detected sbt version #{version}")
83
+ version
84
+ }
85
+ _cset(:sbt_group_id) {
86
+ case sbt_version
87
+ when /^0\.(?:7|10)\.\d+$/, /^0\.11\.[0-2]$/
88
+ "org.scala-tools.sbt"
46
89
  else
47
- "#{env} #{java} -jar #{sbt_jar_file} #{sbt_options.join(' ')}".strip
90
+ "org.scala-sbt"
48
91
  end
49
92
  }
50
- _cset(:sbt_cmd_local) {
51
- if fetch(:sbt_java_home_local, nil)
52
- env = "env JAVA_HOME=#{sbt_java_home_local.dump}"
53
- java = "#{sbt_java_home_local}/bin/java"
93
+ _cset(:sbt_launch_jar_url) {
94
+ if exists?(:sbt_jar_url)
95
+ logger.info(":sbt_jar_url has been deprecated. use :sbt_launch_jar_url instead.")
96
+ fetch(:sbt_jar_url)
97
+ else
98
+ "http://typesafe.artifactoryonline.com/typesafe/ivy-releases/#{sbt_group_id}/sbt-launch/#{sbt_version}/sbt-launch.jar"
54
99
  end
55
- if sbt_use_extras
56
- "#{env} #{sbt_extras_file_local} #{sbt_options_local.join(' ')}".strip
100
+ }
101
+ _cset(:sbt_launch_jar) {
102
+ if exists?(:sbt_jar_file)
103
+ logger.info(":sbt_jar_file has been deprecated. use :sbt_launch_jar instead.")
104
+ fetch(:sbt_jar_file)
57
105
  else
58
- "#{env} #{java} -jar #{sbt_jar_file_local} #{sbt_options_local.join(' ')}".strip
106
+ File.join(sbt_path, "sbt-launch.jar")
59
107
  end
60
108
  }
61
- _cset(:sbt_project_path) {
62
- release_path
109
+ _cset(:sbt_launch_jar_local) {
110
+ if exists?(:sbt_jar_file_local)
111
+ logger.info(":sbt_jar_file_local has been deprecated. use :sbt_launch_jar_local instead.")
112
+ fetch(:sbt_jar_file_local)
113
+ else
114
+ File.join(sbt_path_local, "sbt-launch.jar")
115
+ end
63
116
  }
64
- _cset(:sbt_project_path_local) {
65
- Dir.pwd
117
+ _cset(:sbt_launch_jar_script) {
118
+ (<<-EOS).gsub(/^\s*/, "")
119
+ #!/bin/sh -e
120
+ java -Xms512M -Xmx1536M -Xss1M -XX:+CMSClassUnloadingEnabled -XX:MaxPermSize=384M -jar `dirname $0`/sbt-launch.jar "$@"
121
+ EOS
66
122
  }
67
- _cset(:sbt_target_path) {
68
- File.join(sbt_project_path, 'target')
123
+
124
+ ## SBT environment
125
+ _cset(:sbt_common_environment, {})
126
+ _cset(:sbt_default_environment) {
127
+ environment = {}
128
+ environment["JAVA_HOME"] = fetch(:sbt_java_home) if exists?(:sbt_java_home)
129
+ environment["PATH"] = [ sbt_bin_path, "$PATH" ].join(":") if sbt_setup_remotely
130
+ _merge_environment(sbt_common_environment, environment)
69
131
  }
70
- _cset(:sbt_target_path_local) {
71
- File.join(sbt_project_path_local, File.basename(sbt_target_path))
132
+ _cset(:sbt_default_environment_local) {
133
+ environment = {}
134
+ environment["JAVA_HOME"] = fetch(:sbt_java_home_local) if exists?(:sbt_java_home_local)
135
+ environment["PATH"] = [ sbt_bin_path, "$PATH" ].join(":") if sbt_setup_locally
136
+ _merge_environment(sbt_common_environment, environment)
72
137
  }
73
- _cset(:sbt_template_path, File.join(File.dirname(__FILE__), 'templates'))
74
- _cset(:sbt_update_settings, false)
75
- _cset(:sbt_update_settings_locally, false)
76
- _cset(:sbt_settings_path) { File.join(sbt_project_path, 'sbt') }
77
- _cset(:sbt_settings_path_local) { File.join(sbt_project_path_local, 'sbt') }
78
- _cset(:sbt_settings, [])
79
- _cset(:sbt_settings_local, [])
80
- _cset(:sbt_cleanup_settings, [])
81
- _cset(:sbt_cleanup_settings_local, [])
82
- _cset(:sbt_compile_locally, false) # perform precompilation on localhost
138
+ _cset(:sbt_environment) { _merge_environment(sbt_default_environment, fetch(:sbt_extra_environment, {})) }
139
+ _cset(:sbt_environment_local) { _merge_environment(sbt_default_environment_local, fetch(:sbt_extra_environment_local, {})) }
140
+ def _command(cmdline, options={})
141
+ environment = options.fetch(:env, {})
142
+ if environment.empty?
143
+ cmdline
144
+ else
145
+ env = (["env"] + environment.map { |k, v| "#{k}=#{v.dump}" }).join(" ")
146
+ "#{env} #{cmdline}"
147
+ end
148
+ end
149
+ def command(cmdline, options={})
150
+ _command(cmdline, :env => sbt_environment.merge(options.fetch(:env, {})))
151
+ end
152
+ def command_local(cmdline, options={})
153
+ _command(cmdline, :env => sbt_environment_local.merge(options.fetch(:env, {})))
154
+ end
155
+ _cset(:sbt_cmd) { command("#{sbt_bin.dump} #{sbt_options.map { |x| x.dump }.join(" ")}") }
156
+ _cset(:sbt_cmd_local) { command_local("#{sbt_bin_local.dump} #{sbt_options_local.map { |x| x.dump }.join(" ")}") }
83
157
  _cset(:sbt_goals, %w(reload clean package))
84
158
  _cset(:sbt_common_options) {
85
159
  options = []
86
160
  if fetch(:sbt_log_noformat, true)
87
- options << if sbt_use_extras
88
- "-no-colors"
89
- else
90
- "-Dsbt.log.noformat=true"
91
- end
161
+ if sbt_use_extras
162
+ options << "-no-colors"
163
+ else
164
+ options << "-Dsbt.log.noformat=true"
165
+ end
92
166
  end
93
167
  options
94
168
  }
95
- _cset(:sbt_options) {
96
- options = sbt_common_options + fetch(:sbt_extra_options, [])
169
+ _cset(:sbt_default_options) {
170
+ options = sbt_common_options.dup
97
171
  if sbt_update_settings
98
- options << if sbt_use_extras
99
- "-sbt-dir #{sbt_settings_path}"
100
- else
101
- "-Dsbt.global.base=#{sbt_settings_path}"
102
- end
172
+ if sbt_use_extras
173
+ options += ["-sbt-dir", sbt_settings_path]
174
+ else
175
+ options << "-Dsbt.global.base=#{sbt_settings_path}"
176
+ end
103
177
  end
104
178
  options
105
179
  }
106
- _cset(:sbt_options_local) {
107
- options = sbt_common_options + fetch(:sbt_extra_options_local, [])
180
+ _cset(:sbt_default_options_local) {
181
+ options = sbt_common_options.dup
108
182
  if sbt_update_settings_locally
109
- options << if sbt_use_extras
110
- "-sbt-dir #{sbt_settings_path_local}"
111
- else
112
- "-Dsbt.global.base=#{sbt_settings_path_local}"
113
- end
183
+ if sbt_use_extras
184
+ options += ["-sbt-dir", sbt_settings_path_local]
185
+ else
186
+ options << "-Dsbt.global.base=#{sbt_settings_path_local}"
187
+ end
114
188
  end
115
189
  options
116
190
  }
191
+ _cset(:sbt_options) { sbt_default_options + fetch(:sbt_extra_options, []) }
192
+ _cset(:sbt_options_local) { sbt_default_options_local + fetch(:sbt_extra_options_local, []) }
117
193
 
118
- desc("Setup sbt.")
119
- task(:setup, :roles => :app, :except => { :no_release => true }) {
120
- transaction {
121
- install
122
- update_settings if sbt_update_settings
123
- setup_locally if sbt_compile_locally
124
- }
194
+ _cset(:sbt_setup_remotely) { sbt_update_remotely }
195
+ _cset(:sbt_setup_locally) { sbt_update_locally }
196
+ _cset(:sbt_update_remotely) { not(sbt_update_locally) }
197
+ _cset(:sbt_update_locally) { # perform update on localhost
198
+ if exists?(:sbt_compile_locally)
199
+ logger.info(":sbt_compile_locally has been deprecated. use :sbt_update_locally instead.")
200
+ fetch(:sbt_compile_locally, false)
201
+ else
202
+ false
203
+ end
125
204
  }
126
- after 'deploy:setup', 'sbt:setup'
127
205
 
128
- desc("Setup sbt locally.")
129
- task(:setup_locally, :except => { :no_release => true }) {
130
- transaction {
131
- install_locally
132
- update_settings_locally if sbt_update_settings_locally
206
+ if top.namespaces.key?(:multistage)
207
+ after "multistage:ensure", "sbt:setup_default_environment"
208
+ else
209
+ on :start do
210
+ if top.namespaces.key?(:multistage)
211
+ after "multistage:ensure", "sbt:setup_default_environment"
212
+ else
213
+ setup_default_environment
214
+ end
215
+ end
216
+ end
217
+
218
+ _cset(:sbt_environment_join_keys, %w(DYLD_LIBRARY_PATH LD_LIBRARY_PATH MANPATH PATH))
219
+ def _merge_environment(x, y)
220
+ x.merge(y) { |key, x_val, y_val|
221
+ if sbt_environment_join_keys.include?(key)
222
+ ( y_val.split(":") + x_val.split(":") ).uniq.join(":")
223
+ else
224
+ y_val
225
+ end
133
226
  }
227
+ end
228
+
229
+ task(:setup_default_environment, :roles => sbt_roles, :except => { :no_release => true }) {
230
+ if fetch(:sbt_setup_default_environment, true)
231
+ set(:default_environment, _merge_environment(default_environment, sbt_environment))
232
+ end
134
233
  }
135
234
 
136
- def _install(options={})
235
+ def _invoke_command(cmdline, options={})
236
+ if options[:via] == :run_locally
237
+ run_locally(cmdline)
238
+ else
239
+ invoke_command(cmdline, options)
240
+ end
241
+ end
242
+
243
+ def _download_extras(uri, filename, options={})
137
244
  execute = []
138
- if sbt_use_extras
139
- extras_file = options.delete(:extras_file)
140
- execute << "mkdir -p #{File.dirname(extras_file)}"
141
- x = "/tmp/sbt-extras.#{$$}"
142
- execute << "touch -t #{sbt_extras_check_timestamp} #{x}"
143
- execute << "( test #{extras_file} -nt #{x} || wget --no-verbose -O #{extras_file} #{sbt_extras_url} )"
144
- execute << "touch #{extras_file}"
145
- execute << "rm -f #{x}"
146
- execute << "( test -x #{extras_file} || chmod a+x #{extras_file} )"
245
+ execute << "mkdir -p #{File.dirname(filename).dump}"
246
+ if fetch(:sbt_update_extras, true)
247
+ execute << %{t=$(mktemp /tmp/sbt.XXXXXXXXXX)}
248
+ execute << %{touch -t #{sbt_extras_update_timestamp.dump} "$t"}
249
+ execute << %{( test #{filename.dump} -nt "$t" || wget --no-verbose -O #{filename.dump} #{uri.dump}; rm -f "$t" )}
250
+ else
251
+ execute << %{( test -f #{filename.dump} || wget --no-verbose -O #{filename.dump} #{uri.dump} )}
252
+ end
253
+ execute << %{( test -x #{filename.dump} || chmod 755 #{filename.dump} )}
254
+ _invoke_command(execute.join(" && "), options)
255
+ end
256
+
257
+ def _download_launch_jar(uri, filename, options={})
258
+ execute = []
259
+ execute << "mkdir -p #{File.dirname(filename).dump}"
260
+ execute << "( test -f #{filename.dump} || wget --no-verbose -O #{filename.dump} #{uri.dump} )"
261
+ _invoke_command(execute.join(" && "), options)
262
+ end
263
+
264
+ def _upload(filename, remote_filename, options={})
265
+ mode = options.delete(:mode)
266
+ _invoke_command("mkdir -p #{File.dirname(remote_filename).dump}", options)
267
+ transfer_if_modified(:up, filename, remote_filename, fetch(:sbt_upload_options, {}).merge(options))
268
+ if mode
269
+ mode = mode.is_a?(Numeric) ? mode.to_s(8) : mode.to_s
270
+ _invoke_command("chmod #{mode.dump} #{remote_filename.dump}", options)
271
+ end
272
+ end
273
+
274
+ def _install_extras(filename, options={})
275
+ # nop
276
+ end
277
+
278
+ def _install_launch_jar(jar, sbt, options={})
279
+ via = options.delete(:via)
280
+ if via == :run_locally
281
+ run_locally("mkdir -p #{File.dirname(sbt).dump}")
282
+ File.write(sbt, sbt_launch_jar_script)
283
+ run_locally("( test -x #{sbt.dump} || chmod 755 #{sbt.dump} )")
147
284
  else
148
- jar_file = options.delete(:jar_file)
149
- execute << "mkdir -p #{File.dirname(jar_file)}"
150
- execute << "( test -f #{jar_file} || wget --no-verbose -O #{jar_file} #{sbt_jar_url} )"
151
- execute << "test -f #{jar_file}"
285
+ safe_put(sbt_launch_jar_script, sbt, {:mode => "755", :run_method => via}.merge(options))
152
286
  end
153
- execute.join(' && ')
154
287
  end
155
288
 
156
- task(:install, :roles => :app, :except => { :no_release => true }) {
157
- run(_install(:jar_file => sbt_jar_file, :extras_file => sbt_extras_file))
289
+ def _installed?(destination, options={})
290
+ sbt = File.join(destination, "sbt")
291
+ cmdline = "test -d #{destination.dump} && test -x #{sbt.dump}"
292
+ _invoke_command(cmdline, options)
293
+ true
294
+ rescue
295
+ false
296
+ end
297
+
298
+ ## setup
299
+ desc("Setup sbt.")
300
+ task(:setup, :roles => sbt_roles, :except => { :no_release => true }) {
301
+ transaction {
302
+ setup_remotely if sbt_setup_remotely
303
+ setup_locally if sbt_setup_locally
304
+ }
158
305
  }
306
+ after "deploy:setup", "sbt:setup"
159
307
 
160
- task(:install_locally, :except => { :no_release => true }) {
161
- run_locally(_install(:jar_file => sbt_jar_file_local, :extras_file => sbt_extras_file_local))
308
+ task(:setup_remotely, :roles => sbt_roles, :except => { :no_release => true }) {
309
+ if sbt_use_extras
310
+ _download_extras(sbt_extras_url, sbt_bin_local, :via => :run_locally)
311
+ _upload(sbt_bin_local, sbt_bin, :mode => "755")
312
+ unless _installed?(sbt_path)
313
+ _install_extras(sbt_bin)
314
+ end
315
+ else
316
+ _download_launch_jar(sbt_launch_jar_url, sbt_launch_jar_local, :via => :run_locally)
317
+ _upload(sbt_launch_jar_local, sbt_launch_jar, :mode => "644")
318
+ unless _installed?(sbt_path)
319
+ _install_launch_jar(sbt_launch_jar, sbt_bin)
320
+ end
321
+ end
322
+ _installed?(sbt_path)
323
+ update_settings if sbt_update_settings
324
+ }
325
+
326
+ desc("Setup sbt locally.")
327
+ task(:setup_locally, :roles => sbt_roles, :except => { :no_release => true }) {
328
+ if sbt_use_extras
329
+ _download_extras(sbt_extras_url, sbt_bin_local, :via => :run_locally)
330
+ unless _installed?(sbt_path_local, :via => :run_locally)
331
+ _install_extras(sbt_bin_local, :via => :run_locally)
332
+ end
333
+ else
334
+ _download_launch_jar(sbt_launch_jar_url, sbt_launch_jar_local, :via => :run_locally)
335
+ unless _installed?(sbt_path_local, :via => :run_locally)
336
+ _install_launch_jar(sbt_launch_jar_local, sbt_bin_local, :via => :run_locally)
337
+ end
338
+ end
339
+ _installed?(sbt_path_local, :via => :run_locally)
340
+ update_settings_locally if sbt_update_settings_locally
162
341
  }
163
342
 
164
- task(:update_settings, :roles => :app, :except => { :no_release => true }) {
165
- sbt_settings.each do |f|
166
- safe_put(template(f, :path => sbt_template_path), File.join(sbt_settings_path, f))
343
+ _cset(:sbt_update_settings) { sbt_setup_remotely and not(sbt_settings.empty?) }
344
+ _cset(:sbt_update_settings_locally) { sbt_setup_locally and not(sbt_settings_local.empty?) }
345
+ _cset(:sbt_settings_path) { File.join(sbt_project_path, "sbt") } # sbt.global.base
346
+ _cset(:sbt_settings_path_local) { File.join(sbt_project_path_local, "sbt") } # sbt.global.base
347
+ _cset(:sbt_settings, [])
348
+ _cset(:sbt_settings_local) { sbt_settings }
349
+ task(:update_settings, :roles => sbt_roles, :except => { :no_release => true }) {
350
+ sbt_settings.each do |file|
351
+ safe_put(template(file, :path => sbt_template_path), File.join(sbt_settings_path, file))
167
352
  end
168
- run("rm -f #{sbt_cleanup_settings.map { |x| x.dump }.join(' ')}") unless sbt_cleanup_settings.empty?
169
353
  }
170
354
 
171
- task(:update_settings_locally, :except => { :no_release => true }) {
172
- sbt_settings_local.each do |f|
173
- File.write(File.join(sbt_settings_path_local, f), template(f, :path => sbt_template_path))
355
+ task(:update_settings_locally, :rols => sbt_roles, :except => { :no_release => true }) {
356
+ sbt_settings_local.each do |file|
357
+ destination = File.join(sbt_settings_path_local, file)
358
+ run_locally("mkdir -p #{File.dirname(destination).dump}")
359
+ File.write(destination, template(file, :path => sbt_template_path))
174
360
  end
175
- run_locally("rm -f #{sbt_cleanup_settings_local.map { |x| x.dump }.join(' ')}") unless sbt_cleanup_settings_local.empty?
176
361
  }
177
362
 
363
+ ## update
178
364
  desc("Update sbt build.")
179
- task(:update, :roles => :app, :except => { :no_release => true }) {
365
+ task(:update, :roles => sbt_roles, :except => { :no_release => true }) {
180
366
  transaction {
181
- if sbt_compile_locally
182
- update_locally
183
- else
184
- execute
185
- end
367
+ update_remotely if sbt_update_remotely
368
+ update_locally if sbt_update_locally
186
369
  }
187
370
  }
188
- after 'deploy:finalize_update', 'sbt:update'
371
+ _cset(:sbt_update_hook_type, :after)
372
+ _cset(:sbt_update_hook, "deploy:finalize_update")
373
+ on(:start) do
374
+ [ sbt_update_hook ].flatten.each do |hook|
375
+ send(sbt_update_hook_type, hook, "sbt:update") if hook
376
+ end
377
+ end
189
378
 
190
- desc("Update sbt build locally.")
191
- task(:update_locally, :except => { :no_release => true }) {
192
- transaction {
193
- execute_locally
194
- upload_locally
195
- }
379
+ task(:update_remotely, :roles => sbt_roles, :except => { :no_release => true }) {
380
+ execute_remotely
196
381
  }
197
382
 
198
- def _sbt(cmd, path, goals=[])
199
- "cd #{path.dump} && #{cmd} #{goals.map { |s| s.dump }.join(' ')}"
200
- end
383
+ desc("Update sbt build locally.")
384
+ task(:update_locally, :roles => sbt_roles, :except => { :no_release => true }) {
385
+ execute_locally
386
+ upload_locally
387
+ }
201
388
 
202
- def _sbt_parse_version(s)
389
+ def _parse_project_version(s)
203
390
  # FIXME: is there any better way to get project version?
204
391
  lastline = s.split(/(?:\r?\n)+/)[-1]
205
392
  lastline.split[-1]
206
393
  end
207
394
 
208
- _cset(:sbt_release_build, false)
209
- _cset(:sbt_snapshot_pattern, /-SNAPSHOT$/i)
210
395
  _cset(:sbt_project_version) {
211
- _sbt_parse_version(capture(_sbt(sbt_cmd, sbt_project_path, ["show version"])))
396
+ _parse_project_version(sbt.exec(["show version"], :via => :capture))
212
397
  }
213
398
  _cset(:sbt_project_version_local) {
214
- _sbt_parse_version(run_locally(_sbt(sbt_cmd_local, sbt_project_path_local, ["show version"])))
399
+ _parse_project_version(sbt.exec_locally(["show version"], :via => :capture_locally))
215
400
  }
216
-
217
- def _validate_project_version(version_key)
218
- if sbt_release_build
219
- version = fetch(version_key)
220
- if sbt_snapshot_pattern === version
221
- abort("Skip to build project since \`#{version}' is a SNAPSHOT version.")
222
- end
401
+ _cset(:sbt_snapshot_pattern, /-SNAPSHOT$/i)
402
+ def _validate_project_version(key)
403
+ if fetch(:sbt_release_build, false)
404
+ version = fetch(key)
405
+ abort("Skip to build project since \`#{version}' is a SNAPSHOT version.") if sbt_snapshot_pattern === version
223
406
  end
224
407
  end
225
408
 
226
409
  desc("Perform sbt build.")
227
- task(:execute, :roles => :app, :except => { :no_release => true }) {
228
- on_rollback {
229
- run(_sbt(sbt_cmd, sbt_project_path, %w(clean)))
230
- }
410
+ task(:execute, :roles => sbt_roles, :except => { :no_release => true }) {
411
+ execute_remotely
412
+ }
413
+
414
+ task(:execute_remotely, :roles => sbt_roles, :except => { :no_release => true }) {
415
+ on_rollback do
416
+ sbt.exec("clean")
417
+ end
231
418
  _validate_project_version(:sbt_project_version)
232
- run(_sbt(sbt_cmd, sbt_project_path, sbt_goals))
419
+ sbt.exec(sbt_goals)
233
420
  }
234
421
 
235
422
  desc("Perform sbt build locally.")
236
- task(:execute_locally, :roles => :app, :except => { :no_release => true }) {
423
+ task(:execute_locally, :roles => sbt_roles, :except => { :no_release => true }) {
237
424
  on_rollback {
238
- run_locally(_sbt(sbt_cmd_local, sbt_project_path_local, %w(clean)))
425
+ sbt.exec_locally("clean")
239
426
  }
240
427
  _validate_project_version(:sbt_project_version_local)
241
- cmdline = _sbt(sbt_cmd_local, sbt_project_path_local, sbt_goals)
242
- logger.info(cmdline)
243
- abort("execution failure") unless system(cmdline)
428
+ sbt.exec_locally(sbt_goals)
244
429
  }
245
430
 
246
- _cset(:sbt_tar, 'tar')
247
- _cset(:sbt_tar_local, 'tar')
248
- _cset(:sbt_target_archive) {
249
- "#{sbt_target_path}.tar.gz"
250
- }
251
- _cset(:sbt_target_archive_local) {
252
- "#{sbt_target_path_local}.tar.gz"
253
- }
254
- task(:upload_locally, :roles => :app, :except => { :no_release => true }) {
255
- on_rollback {
256
- run("rm -rf #{sbt_target_path} #{sbt_target_archive}")
257
- }
431
+ task(:upload_locally, :rolse => sbt_roles, :except => { :no_release => true }) {
432
+ on_rollback do
433
+ run("rm -rf #{sbt_target_path.dump}")
434
+ end
435
+ filename = "#{sbt_target_path_local}.tar.gz"
436
+ remote_filename = "#{sbt_target_path}.tar.gz"
258
437
  begin
259
- run_locally("cd #{File.dirname(sbt_target_path_local)} && #{sbt_tar_local} chzf #{sbt_target_archive_local} #{File.basename(sbt_target_path_local)}")
260
- upload(sbt_target_archive_local, sbt_target_archive)
261
- run("cd #{File.dirname(sbt_target_path)} && #{sbt_tar} xzf #{sbt_target_archive} && rm -f #{sbt_target_archive}")
438
+ run_locally("cd #{File.dirname(sbt_target_path_local).dump} && tar chzf #{filename.dump} #{File.basename(sbt_target_path_local).dump}")
439
+ run("mkdir -p #{File.dirname(sbt_target_path).dump}")
440
+ top.upload(filename, remote_filename)
441
+ run("cd #{File.dirname(sbt_target_path).dump} && tar xzf #{remote_filename.dump}")
262
442
  ensure
263
- run_locally("rm -f #{sbt_target_archive_local}")
443
+ run("rm -f #{remote_filename.dump}") rescue nil
444
+ run_locally("rm -f #{filename.dump}") rescue nil
264
445
  end
265
446
  }
447
+
448
+ def _exec_command(args=[], options={})
449
+ args = [ args ].flatten
450
+ sbt = options.fetch(:sbt, "sbt")
451
+ execute = []
452
+ execute << "cd #{options[:path].dump}" if options.key?(:path)
453
+ execute << "#{sbt} #{args.map { |x| x.dump }.join(" ")}"
454
+ execute.join(" && ")
455
+ end
456
+
457
+ ## public methods
458
+ def exec(args=[], options={})
459
+ cmdline = _exec_command(args, { :path => sbt_project_path, :sbt => sbt_cmd, :via => :run }.merge(options))
460
+ _invoke_command(cmdline, options)
461
+ end
462
+
463
+ def exec_locally(args=[], options={})
464
+ via = options.delete(:via)
465
+ cmdline = _exec_command(args, { :path => sbt_project_path_local, :sbt => sbt_cmd_local, :via => :run_locally }.merge(options))
466
+ if via == :capture_locally
467
+ _invoke_command(cmdline, options.merge(:via => :run_locally))
468
+ else
469
+ logger.trace("executing locally: #{cmdline.dump}")
470
+ elapsed = Benchmark.realtime do
471
+ system(cmdline)
472
+ end
473
+ if $?.to_i > 0 # $? is command exit code (posix style)
474
+ raise Capistrano::LocalArgumentError, "Command #{cmd} returned status code #{$?}"
475
+ end
476
+ logger.trace "command finished in #{(elapsed * 1000).round}ms"
477
+ end
478
+ end
266
479
  }
267
480
  }
268
481
  end
@@ -270,7 +483,7 @@ module Capistrano
270
483
  end
271
484
 
272
485
  if Capistrano::Configuration.instance
273
- Capistrano::Configuration.instance.extend(Capistrano::Sbt)
486
+ Capistrano::Configuration.instance.extend(Capistrano::SBT)
274
487
  end
275
488
 
276
489
  # vim:set ft=ruby :