Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 16 additions & 3 deletions client.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,6 @@ import (
"github.com/pkg/sftp/v2/encoding/ssh/filexfer/openssh"
"github.com/pkg/sftp/v2/internal/pragma"
"github.com/pkg/sftp/v2/internal/sync"

"golang.org/x/crypto/ssh"
)

type result struct {
Expand Down Expand Up @@ -579,9 +577,24 @@ func (cl *Client) getDataBuf(size int) []byte {
return hint[:size] // trim our buffer to length, it might be longer than chunkSize.
}

type SSHSession interface {
StdinPipe() (io.WriteCloser, error)
StdoutPipe() (io.Reader, error)
StderrPipe() (io.Reader, error)

RequestSubsystem(subsystem string) error

Close() error
Wait() error
}

type SSHClient[Session SSHSession] interface {
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have to use a generic type here, because NewSession returns a type that is specific to ssh package, which would require us to pull in that package as well… but now we have generics, so we can say, “I know it returns a type that matches this interface, so use that as a type constraint.”

NewSession() (Session, error)
}

// NewClient creates a new SFTP client on conn.
// The context is only used during initialization, and handshake.
func NewClient(ctx context.Context, conn *ssh.Client, opts ...ClientOption) (*Client, error) {
func NewClient[CL SSHClient[SESS], SESS SSHSession](ctx context.Context, conn CL, opts ...ClientOption) (*Client, error) {
s, err := conn.NewSession()
if err != nil {
return nil, err
Expand Down
12 changes: 12 additions & 0 deletions examples/go.mod
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We add this sub-module to isolate the import of x/crypto because the examples need the import, even though the rest of the module doesn’t.

Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
module github.com/pkg/sftp/v2/examples

go 1.25

require (
github.com/pkg/sftp/v2 v2.0.0-alpha
golang.org/x/crypto v0.36.0
)

require golang.org/x/sys v0.31.0 // indirect

replace github.com/pkg/sftp/v2 => ..
8 changes: 8 additions & 0 deletions examples/go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34=
golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc=
golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/term v0.30.0 h1:PQ39fJZ+mfadBm0y5WlL4vlM7Sx1Hgf13sMIY2+QS9Y=
golang.org/x/term v0.30.0/go.mod h1:NYYFdzHoI5wRh/h5tDMdMqCqPJZEuNqVR5xJLd/n67g=
1 change: 0 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,5 @@ go 1.25

require (
github.com/google/go-cmp v0.6.0
golang.org/x/crypto v0.36.0
golang.org/x/sys v0.31.0
)
4 changes: 0 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34=
golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc=
golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/term v0.30.0 h1:PQ39fJZ+mfadBm0y5WlL4vlM7Sx1Hgf13sMIY2+QS9Y=
golang.org/x/term v0.30.0/go.mod h1:NYYFdzHoI5wRh/h5tDMdMqCqPJZEuNqVR5xJLd/n67g=
Loading