mirror of
https://github.com/capistrano/capistrano
synced 2023-03-27 23:21:18 -04:00
Monkey patch SSHKit to expose current backend
Eventually this will be part of SSHKit itself, but for flexibility in using Capistrano with older SSHKit versions, I'm including this here as a monkey patch. The point of SSHKit::Backend.current is to give code access to the current Backend without having to pass around a reference to it. For example, consider a `git` helper that executes a git command: def git(*args) SSHKit::Backend.current.execute(:git, *args) end Thanks to `current`, we can use this git method wherever we are in an `on` block, without having to pass a reference to `self`: on release_roles(:all) do git "status" end Without the thread local, the same task would be much more awkward due to the necessary passing of `self`: def git(backend, *args) backend.execute(:git, *args) end on release_roles(:all) do git self, "status" end To someone not intimately familiar with SSHKit, what `self` in this context is confusing and not obvious at all. It is because SSHKit uses `instance_exec` within the `on` block that `self` magically transforms. Better to avoid using `self` altogether and prefer the thread local.
This commit is contained in:
parent
9168947002
commit
3b9c90327b
2 changed files with 55 additions and 0 deletions
25
lib/capistrano/ext/sshkit/backend/thread_local.rb
Normal file
25
lib/capistrano/ext/sshkit/backend/thread_local.rb
Normal file
|
@ -0,0 +1,25 @@
|
|||
require "sshkit/backends/abstract"
|
||||
|
||||
# Monkey patch older versions of SSHKit to make the currently-executing Backend
|
||||
# available via a thread local value.
|
||||
#
|
||||
# TODO: Remove this code once capistrano.gemspec requires newer SSHKit version.
|
||||
|
||||
unless SSHKit::Backend.respond_to?(:current)
|
||||
module SSHKit
|
||||
module Backend
|
||||
def self.current
|
||||
Thread.current["sshkit_backend"]
|
||||
end
|
||||
|
||||
class Abstract
|
||||
def run
|
||||
Thread.current["sshkit_backend"] = self
|
||||
instance_exec(@host, &@block)
|
||||
ensure
|
||||
Thread.current["sshkit_backend"] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
30
spec/lib/capistrano/ext/sshkit/backend/thread_local_spec.rb
Normal file
30
spec/lib/capistrano/ext/sshkit/backend/thread_local_spec.rb
Normal file
|
@ -0,0 +1,30 @@
|
|||
require "spec_helper"
|
||||
require "capistrano/ext/sshkit/backend/thread_local"
|
||||
|
||||
module SSHKit
|
||||
module Backend
|
||||
describe "#current" do
|
||||
require "sshkit/dsl"
|
||||
|
||||
it "refers to the currently executing backend" do
|
||||
backend = nil
|
||||
current = nil
|
||||
|
||||
on(:local) do
|
||||
backend = self
|
||||
current = SSHKit::Backend.current
|
||||
end
|
||||
|
||||
expect(current).to eq(backend)
|
||||
end
|
||||
|
||||
it "is nil outside of an on block" do
|
||||
on(:local) do
|
||||
# nothing
|
||||
end
|
||||
|
||||
expect(SSHKit::Backend.current).to be_nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Reference in a new issue