Cleanup ExecRemote code:

* Replace action extension with simple closure composition
* Separate remote and local execution
This commit is contained in:
Pavel Punegov
2017-10-30 15:03:27 +03:00
committed by Pavel Punegov
parent 0623bb9474
commit a3ad2101f5
@@ -22,74 +22,81 @@ import org.gradle.process.ExecResult
import org.gradle.process.ExecSpec
import org.gradle.util.ConfigureUtil
// This class provides process.execRemote -- a drop-in replacement for process.exec .
// If we provide -Premote=user@host the binaries are executed on a remote host
// If we omit -Premote then the binary is executed locally as usual.
import java.nio.file.Paths
import java.util.function.Function
/**
* This class provides process.execRemote -- a drop-in replacement for process.exec.
* If we provide -Premote=user@host the binaries are executed on a remote host
* If we omit -Premote then the binary is executed locally as usual.
*/
class ExecRemote {
private final Project project
private final String remote = null
private final String remoteDir = null
private final Function<Closure<? super ExecSpec>, ExecResult> executor
ExecRemote(Project project) {
this.project = project
if (project.hasProperty('remote')) {
remote = project.ext.remote
remoteDir = uniqSessionName()
createRemoteDir()
}
}
private String uniqSessionName() {
def date = new Date().format('yyyyMMddHHmmss')
return project.ext.remoteRoot + File.createTempFile(System.properties['user.name'], "_" + date)
}
private createRemoteDir() {
project.exec {
commandLine('ssh', remote, 'mkdir', '-p', remoteDir)
if (project.hasProperty('remote')) {
def remote = project.property('remote') as String
executor = new SSHExecutor(remote)
} else {
executor = { project.exec(ConfigureUtil.configureUsing(it)) }
}
}
private upload(String fileName) {
project.exec {
commandLine('scp', fileName, "${remote}:${remoteDir}")
}
ExecResult execRemote(Action<? super ExecSpec> action) {
project.exec(action)
}
private cleanup(String fileName) {
println "Remove ${remote}:${fileName}"
project.exec {
commandLine('ssh', remote, 'rm', fileName )
}
ExecResult execRemote(Closure<? super ExecSpec> closure) {
this.executor.apply(closure)
}
public ExecResult execRemote(Action<? super ExecSpec> action) {
String execFile
Action<? super ExecSpec> extendedAction = new Action<ExecSpec>() {
@Override
void execute(ExecSpec execSpec) {
action.execute(execSpec)
private class SSHExecutor implements Function<Closure<? super ExecSpec>, ExecResult> {
private final String remote
private final String remoteDir
if (remote == null) return
SSHExecutor(String remote) {
this.remote = remote
this.remoteDir = uniqueSessionName()
createRemoteDir()
}
execSpec.with {
upload(getExecutable())
executable = "$remoteDir/${new File(executable).name}"
execFile = executable
if (project.hasProperty('remote')) {
commandLine = ['/usr/bin/ssh', remote] + commandLine
}
}
@Override
ExecResult apply(Closure<? super ExecSpec> closure) {
String execFile
def execResult = project.exec closure >> {
upload(executable)
execFile = executable = "$remoteDir/${new File(executable).name}"
commandLine = ['/usr/bin/ssh', remote] + commandLine
}
if (execFile != null) cleanup(execFile)
return execResult
}
private String uniqueSessionName() {
def date = new Date().format('yyyyMMddHHmmss')
Paths.get(project.ext.remoteRoot.toString(), "tmp",
System.properties['user.name'].toString() + "_" + date).toString()
}
private createRemoteDir() {
project.exec {
commandLine('ssh', remote, 'mkdir', '-p', remoteDir)
}
}
def execResult = project.exec(extendedAction)
if (execFile != null) cleanup(execFile)
return execResult
}
public ExecResult execRemote(Closure closure) {
return this.execRemote(ConfigureUtil.configureUsing(closure));
private upload(String fileName) {
project.exec {
commandLine('scp', fileName, "${remote}:${remoteDir}")
}
}
private cleanup(String fileName) {
project.exec {
commandLine('ssh', remote, 'rm', fileName)
}
}
}
}