Added basic clone code and ssh authentication code using Apache SSHD
This commit is contained in:
parent
ef39c6f6d5
commit
54f013d291
@ -21,6 +21,7 @@ repositories {
|
||||
dependencies {
|
||||
implementation(compose.desktop.currentOs)
|
||||
implementation("org.eclipse.jgit:org.eclipse.jgit:5.13.0.202109080827-r")
|
||||
implementation("org.apache.sshd:sshd-core:2.7.0")
|
||||
}
|
||||
|
||||
tasks.withType<KotlinCompile>() {
|
||||
|
11
src/main/kotlin/credentials/CredentialsStateManager.kt
Normal file
11
src/main/kotlin/credentials/CredentialsStateManager.kt
Normal file
@ -0,0 +1,11 @@
|
||||
package credentials
|
||||
|
||||
class CredentialsStateManager {
|
||||
|
||||
}
|
||||
|
||||
sealed class CredentialsState {
|
||||
object CredentialsRequested: CredentialsState()
|
||||
object CredentialsDenied: CredentialsState()
|
||||
data class CredentialsAccepted(val user: String, val password: String): CredentialsState()
|
||||
}
|
65
src/main/kotlin/credentials/GProcess.kt
Normal file
65
src/main/kotlin/credentials/GProcess.kt
Normal file
@ -0,0 +1,65 @@
|
||||
package credentials
|
||||
|
||||
import org.apache.sshd.client.channel.ChannelExec
|
||||
import org.apache.sshd.client.session.ClientSession
|
||||
import java.io.InputStream
|
||||
import java.io.OutputStream
|
||||
import java.io.PipedInputStream
|
||||
import java.io.PipedOutputStream
|
||||
|
||||
class GProcess : Process() {
|
||||
private lateinit var channel: ChannelExec
|
||||
private val outputStream = PipedOutputStream()
|
||||
private val inputStream = PipedInputStream()
|
||||
private val errorOutputStream = PipedOutputStream()
|
||||
private val pipedInputStream = PipedInputStream(outputStream)
|
||||
private val pipedOutputStream = PipedOutputStream(inputStream)
|
||||
private val pipedErrorInputStream = PipedInputStream(errorOutputStream)
|
||||
|
||||
override fun getOutputStream(): OutputStream {
|
||||
return pipedOutputStream
|
||||
}
|
||||
|
||||
override fun getInputStream(): InputStream {
|
||||
return pipedInputStream
|
||||
}
|
||||
|
||||
override fun getErrorStream(): InputStream {
|
||||
return pipedErrorInputStream
|
||||
}
|
||||
|
||||
override fun waitFor(): Int {
|
||||
if (isRunning())
|
||||
Thread.sleep(100)
|
||||
|
||||
return exitValue()
|
||||
}
|
||||
|
||||
override fun exitValue(): Int {
|
||||
check(!isRunning())
|
||||
|
||||
return channel.exitStatus
|
||||
}
|
||||
|
||||
override fun destroy() {
|
||||
if (channel.isOpen) {
|
||||
channel.close()
|
||||
}
|
||||
}
|
||||
|
||||
private fun isRunning(): Boolean {
|
||||
return channel.exitStatus < 0 && channel.isOpen
|
||||
}
|
||||
|
||||
fun setup(session: ClientSession, commandName: String) {
|
||||
val channel = session.createExecChannel(commandName)
|
||||
channel.out = outputStream
|
||||
channel.err = errorOutputStream
|
||||
channel.`in` = inputStream
|
||||
|
||||
channel.open().verify()
|
||||
|
||||
this.channel = channel
|
||||
}
|
||||
|
||||
}
|
45
src/main/kotlin/credentials/GRemoteSession.kt
Normal file
45
src/main/kotlin/credentials/GRemoteSession.kt
Normal file
@ -0,0 +1,45 @@
|
||||
package credentials
|
||||
|
||||
import org.apache.sshd.client.SshClient
|
||||
import org.apache.sshd.client.future.ConnectFuture
|
||||
import org.eclipse.jgit.transport.RemoteSession
|
||||
import org.eclipse.jgit.transport.URIish
|
||||
import java.io.PipedInputStream
|
||||
import java.io.PipedOutputStream
|
||||
|
||||
private const val DEFAULT_SSH_PORT = 22
|
||||
|
||||
class GRemoteSession : RemoteSession {
|
||||
private val client = SshClient.setUpDefaultClient()
|
||||
|
||||
private var connectFuture: ConnectFuture? = null
|
||||
|
||||
override fun exec(commandName: String, timeout: Int): Process {
|
||||
println(commandName)
|
||||
val connectFuture = checkNotNull(connectFuture)
|
||||
val session = connectFuture.clientSession
|
||||
session.auth().verify()
|
||||
|
||||
val process = GProcess()
|
||||
process.setup(session, commandName)
|
||||
return process
|
||||
}
|
||||
|
||||
override fun disconnect() {
|
||||
client.close()
|
||||
}
|
||||
|
||||
fun setup(uri: URIish) {
|
||||
client.open()
|
||||
|
||||
val port = if (uri.port == -1) {
|
||||
DEFAULT_SSH_PORT
|
||||
} else
|
||||
uri.port
|
||||
|
||||
val connectFuture = client.connect(uri.user, uri.host, port)
|
||||
connectFuture.await()
|
||||
|
||||
this.connectFuture = connectFuture
|
||||
}
|
||||
}
|
29
src/main/kotlin/credentials/GSessionManager.kt
Normal file
29
src/main/kotlin/credentials/GSessionManager.kt
Normal file
@ -0,0 +1,29 @@
|
||||
package credentials
|
||||
|
||||
import org.eclipse.jgit.transport.CredentialsProvider
|
||||
import org.eclipse.jgit.transport.RemoteSession
|
||||
import org.eclipse.jgit.transport.SshSessionFactory
|
||||
import org.eclipse.jgit.transport.URIish
|
||||
import org.eclipse.jgit.util.FS
|
||||
|
||||
class GSessionManager {
|
||||
fun generateSshSessionFactory(): SshSessionFactory {
|
||||
return object : SshSessionFactory() {
|
||||
override fun getSession(
|
||||
uri: URIish,
|
||||
credentialsProvider: CredentialsProvider?,
|
||||
fs: FS?,
|
||||
tms: Int
|
||||
): RemoteSession {
|
||||
val remoteSession = GRemoteSession()
|
||||
remoteSession.setup(uri)
|
||||
return remoteSession
|
||||
}
|
||||
|
||||
override fun getType(): String {
|
||||
return "ssh" //TODO What should be the value of this?
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
56
src/main/kotlin/git/CloneManager.kt
Normal file
56
src/main/kotlin/git/CloneManager.kt
Normal file
@ -0,0 +1,56 @@
|
||||
package git
|
||||
|
||||
import credentials.GRemoteSession
|
||||
import credentials.GSessionManager
|
||||
import org.eclipse.jgit.api.Git
|
||||
import org.eclipse.jgit.transport.*
|
||||
import org.eclipse.jgit.util.FS
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
|
||||
private const val REMOTE_URL = ""
|
||||
|
||||
class CloneManager {
|
||||
private val sessionManager = GSessionManager()
|
||||
|
||||
|
||||
fun cloneTest() {
|
||||
// prepare a new folder for the cloned repository
|
||||
|
||||
// prepare a new folder for the cloned repository
|
||||
val localPath = File.createTempFile("TestGitRepository", "")
|
||||
if (!localPath.delete()) {
|
||||
throw IOException("Could not delete temporary file $localPath")
|
||||
}
|
||||
|
||||
Git.cloneRepository()
|
||||
.setURI(REMOTE_URL)
|
||||
.setDirectory(localPath)
|
||||
.setTransportConfigCallback {
|
||||
if (it is SshTransport) {
|
||||
it.sshSessionFactory = sessionManager.generateSshSessionFactory()
|
||||
} else if (it is HttpTransport) {
|
||||
it.credentialsProvider = object : CredentialsProvider() {
|
||||
override fun isInteractive(): Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
override fun supports(vararg items: CredentialItem?): Boolean {
|
||||
println(items)
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
override fun get(uri: URIish?, vararg items: CredentialItem?): Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
.call().use { result ->
|
||||
// Note: the call() returns an opened repository already which needs to be closed to avoid file handle leaks!
|
||||
println("Having repository: " + result.repository.directory)
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user