Skip to content

Commit

Permalink
Merge pull request #21 from gaetanzanella/feature/api-fine-tuning
Browse files Browse the repository at this point in the history
Feature/api fine tuning
  • Loading branch information
gaetanzanella authored Apr 16, 2023
2 parents 2d8d28a + cf5cba8 commit 933e52c
Show file tree
Hide file tree
Showing 10 changed files with 158 additions and 114 deletions.
34 changes: 25 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,27 +26,43 @@ let connection = SSHConnection(
try await connection.start()
```

Once connected, you can start executing concrete SSH operations on child communication channels. As `SSH Client` means to be a high level interface, you do not directly interact with them. Instead you use interfaces dedicated to your use case.
Once connected, you can start executing concrete SSH operations on child communication channels.
As `SSH Client` means to be a high level interface, you do not directly interact with them.
Instead you use interfaces dedicated to your use case.

- SSH commands
```swift
let response = try await connection.execute("echo Hello\n")
// Handle response

for try await chunk in connection.stream("echo World\n") {
// Handle chunk
}
```

- SSH shell
```swift
let shell = try await connection.requestShell()
for try await chunk in shell.data {
// ...
// Handle chunk
}
```

- SFTP client
```swift
let sftpClient = try await connection.requestSFTPClient()
// sftp operations
```

- SSH commands
```swift
let response = try await connection.execute("echo Hello\n")
// Handle response
```
// directories
try await sftpClient.createDirectory(at: "./new")
try await sftpClient.removeDirectory(at: "./new")

// files
let file = try await client.openFile(at: "./new/file.txt", flags: .create)
try await file.write("Hello World!".data(using: .utf8)!)
try await file.close()

// and more
```

You keep track of the connection state, using the dedicated `stateUpdateHandler` property:
```swift
Expand Down
32 changes: 16 additions & 16 deletions Sources/SSHClient/Async/SFTPClient+Async.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,26 +30,26 @@ public extension SFTPFile {
}

public extension SFTPClient {
func openFile(filePath: String,
func openFile(at filePath: SFTPFilePath,
flags: SFTPOpenFileFlags,
attributes: SFTPFileAttributes = .none) async throws -> SFTPFile {
try await withCheckedResultContinuation { completion in
openFile(
filePath: filePath,
at: filePath,
flags: flags,
attributes: attributes,
completion: completion
)
}
}

func withFile(filePath: String,
func withFile(at filePath: SFTPFilePath,
flags: SFTPOpenFileFlags,
attributes: SFTPFileAttributes = .none,
_ closure: @escaping (SFTPFile) async -> Void) async throws {
try await withCheckedResultContinuation { completion in
withFile(
filePath: filePath,
at: filePath,
flags: flags,
attributes: attributes, { file, close in
Task {
Expand All @@ -62,41 +62,41 @@ public extension SFTPClient {
}
}

func listDirectory(atPath path: String) async throws -> [SFTPPathComponent] {
func listDirectory(at path: SFTPFilePath) async throws -> [SFTPPathComponent] {
try await withCheckedResultContinuation { completion in
listDirectory(atPath: path, completion: completion)
listDirectory(at: path, completion: completion)
}
}

func getAttributes(at filePath: String) async throws -> SFTPFileAttributes {
func getAttributes(at filePath: SFTPFilePath) async throws -> SFTPFileAttributes {
try await withCheckedResultContinuation { completion in
getAttributes(at: filePath, completion: completion)
}
}

func createDirectory(atPath path: String,
func createDirectory(at path: SFTPFilePath,
attributes: SFTPFileAttributes = .none) async throws {
try await withCheckedResultContinuation { completion in
createDirectory(atPath: path, attributes: attributes, completion: completion)
createDirectory(at: path, attributes: attributes, completion: completion)
}
}

func moveItem(atPath current: String,
toPath destination: String) async throws {
func moveItem(at current: SFTPFilePath,
to destination: SFTPFilePath) async throws {
try await withCheckedResultContinuation { completion in
moveItem(atPath: current, toPath: destination, completion: completion)
moveItem(at: current, to: destination, completion: completion)
}
}

func removeDirectory(atPath path: String) async throws {
func removeDirectory(at path: SFTPFilePath) async throws {
try await withCheckedResultContinuation { completion in
removeDirectory(atPath: path, completion: completion)
removeDirectory(at: path, completion: completion)
}
}

func removeFile(atPath path: String) async throws {
func removeFile(at path: SFTPFilePath) async throws {
try await withCheckedResultContinuation { completion in
removeFile(atPath: path, completion: completion)
removeFile(at: path, completion: completion)
}
}

Expand Down
20 changes: 10 additions & 10 deletions Sources/SSHClient/Internal/SFTP/SFTPChannel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@ protocol SFTPChannel {
func readFile(_ file: SFTPMessage.ReadFile.Payload) -> Future<SFTPMessage.ReadFile.Response>
func writeFile(_ file: SFTPMessage.WriteFile.Payload) -> Future<SFTPMessage.Status>
func mkdir(_ dir: SFTPMessage.MkDir.Payload) -> Future<SFTPMessage.Status>
func rmdir(path: String) -> Future<SFTPMessage.Status>
func rmFile(path: String) -> Future<SFTPMessage.Status>
func rmdir(path: SFTPFilePath) -> Future<SFTPMessage.Status>
func rmFile(path: SFTPFilePath) -> Future<SFTPMessage.Status>
func readDir(_ handle: SFTPFileHandle) -> Future<SFTPMessage.ReadDir.Response>
func openDir(path: String) -> Future<SFTPMessage.Handle>
func realpath(path: String) -> Future<SFTPMessage.Name>
func stat(path: String) -> Future<SFTPMessage.Attributes>
func openDir(path: SFTPFilePath) -> Future<SFTPMessage.Handle>
func realpath(path: SFTPFilePath) -> Future<SFTPMessage.Name>
func stat(path: SFTPFilePath) -> Future<SFTPMessage.Attributes>
func rename(_ payload: SFTPMessage.Rename.Payload) -> Future<SFTPMessage.Status>
}

Expand Down Expand Up @@ -118,7 +118,7 @@ class IOSFTPChannel: SFTPChannel {
}
}

func rmdir(path: String) -> Future<SFTPMessage.Status> {
func rmdir(path: SFTPFilePath) -> Future<SFTPMessage.Status> {
allocateRequestID().flatMap { id in
self.send(.rmdir(.init(requestId: id, filePath: path)))
}
Expand All @@ -127,7 +127,7 @@ class IOSFTPChannel: SFTPChannel {
}
}

func rmFile(path: String) -> Future<SFTPMessage.Status> {
func rmFile(path: SFTPFilePath) -> Future<SFTPMessage.Status> {
allocateRequestID().flatMap { id in
self.send(.remove(.init(requestId: id, filename: path)))
}
Expand Down Expand Up @@ -157,7 +157,7 @@ class IOSFTPChannel: SFTPChannel {
}
}

func openDir(path: String) -> Future<SFTPMessage.Handle> {
func openDir(path: SFTPFilePath) -> Future<SFTPMessage.Handle> {
allocateRequestID().flatMap { id in
self.send(.opendir(.init(requestId: id, path: path)))
}
Expand All @@ -171,7 +171,7 @@ class IOSFTPChannel: SFTPChannel {
}
}

func realpath(path: String) -> Future<SFTPMessage.Name> {
func realpath(path: SFTPFilePath) -> Future<SFTPMessage.Name> {
allocateRequestID().flatMap { id in
self.send(.realpath(.init(requestId: id, path: path)))
}
Expand All @@ -185,7 +185,7 @@ class IOSFTPChannel: SFTPChannel {
}
}

func stat(path: String) -> Future<SFTPMessage.Attributes> {
func stat(path: SFTPFilePath) -> Future<SFTPMessage.Attributes> {
allocateRequestID().flatMap { id in
self.send(.stat(.init(requestId: id, path: path)))
}
Expand Down
32 changes: 16 additions & 16 deletions Sources/SSHClient/Internal/SFTP/SFTPMessage.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ typealias SFTPFileHandle = ByteBuffer
typealias SFTPRequestID = UInt32

public struct SFTPPathComponent: Sendable {
public let filename: String
public let filename: SFTPFilePath
public let longname: String
public let attributes: SFTPFileAttributes

init(filename: String, longname: String, attributes: SFTPFileAttributes) {
init(filename: SFTPFilePath, longname: String, attributes: SFTPFileAttributes) {
self.filename = filename
self.longname = longname
self.attributes = attributes
Expand Down Expand Up @@ -125,7 +125,7 @@ enum SFTPMessage {
struct OpenFile {
struct Payload {
// Called `filename` in spec
var filePath: String
var filePath: SFTPFilePath
var pFlags: SFTPOpenFileFlags
var attributes: SFTPFileAttributes
}
Expand Down Expand Up @@ -184,7 +184,7 @@ enum SFTPMessage {

struct Remove {
let requestId: SFTPRequestID
var filename: String
var filename: SFTPFilePath
}

struct FileSetStat {
Expand All @@ -199,7 +199,7 @@ enum SFTPMessage {

struct SetStat {
struct Payload {
var path: String
var path: SFTPFilePath
var attributes: SFTPFileAttributes
}

Expand All @@ -209,8 +209,8 @@ enum SFTPMessage {

struct Symlink {
struct Payload {
var linkPath: String
var targetPath: String
var linkPath: SFTPFilePath
var targetPath: SFTPFilePath
}

let requestId: SFTPRequestID
Expand All @@ -219,7 +219,7 @@ enum SFTPMessage {

struct Readlink {
let requestId: SFTPRequestID
var path: String
var path: SFTPFilePath
}

struct FileData {
Expand All @@ -229,7 +229,7 @@ enum SFTPMessage {

struct MkDir {
struct Payload {
let filePath: String
let filePath: SFTPFilePath
let attributes: SFTPFileAttributes
}

Expand All @@ -239,29 +239,29 @@ enum SFTPMessage {

struct RmDir {
let requestId: SFTPRequestID
var filePath: String
var filePath: SFTPFilePath
}

struct OpenDir {
let requestId: SFTPRequestID
var path: String
var path: SFTPFilePath
}

struct Stat {
static let id = SFTPMessageType.stat

let requestId: SFTPRequestID
var path: String
var path: SFTPFilePath
}

struct LStat {
let requestId: SFTPRequestID
var path: String
var path: SFTPFilePath
}

struct RealPath {
let requestId: SFTPRequestID
var path: String
var path: SFTPFilePath
}

struct Name {
Expand All @@ -282,8 +282,8 @@ enum SFTPMessage {

struct Rename {
struct Payload {
let oldPath: String
let newPath: String
let oldPath: SFTPFilePath
let newPath: SFTPFilePath
}

let requestId: SFTPRequestID
Expand Down
Loading

0 comments on commit 933e52c

Please sign in to comment.