diff --git a/fsimpl/fsimpl_test.go b/fsimpl/fsimpl_test.go index 1819377..ec78abc 100644 --- a/fsimpl/fsimpl_test.go +++ b/fsimpl/fsimpl_test.go @@ -104,6 +104,26 @@ func TestJoinCleanPath(t *testing.T) { args: args{uriParts: nil, trimPrefix: ``, separator: ``}, want: `.`, }, + { + name: `. with sep`, + args: args{uriParts: []string{`.`}, trimPrefix: ``, separator: `/`}, + want: `/`, + }, + { + name: `. without sep`, + args: args{uriParts: []string{`.`}, trimPrefix: ``, separator: ``}, + want: `.`, + }, + { + name: `relative no sep`, + args: args{uriParts: []string{`relative`}, trimPrefix: ``, separator: ``}, + want: `relative`, + }, + { + name: `relative with sep`, + args: args{uriParts: []string{`relative`}, trimPrefix: ``, separator: `/`}, + want: `/relative`, + }, { name: `C:`, args: args{uriParts: nil, trimPrefix: `C:`, separator: `\`}, @@ -124,6 +144,11 @@ func TestJoinCleanPath(t *testing.T) { args: args{uriParts: nil, trimPrefix: `C:\`, separator: `/`}, want: `/`, }, + { + name: `ftp://example.com/dir/subdir/`, + args: args{uriParts: []string{`ftp://example.com/dir/`, `./subdir/`}, trimPrefix: `ftp://`, separator: `/`}, + want: `/example.com/dir/subdir`, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/sftpfs/sftpfs.go b/sftpfs/sftpfs.go index cda3485..f243bec 100644 --- a/sftpfs/sftpfs.go +++ b/sftpfs/sftpfs.go @@ -26,7 +26,7 @@ const ( func init() { // Register with prefix sftp:// for URLs with // sftp://username:password@host:port schema. - fs.Register(new(fileSystem)) + fs.Register(&fileSystem{prefix: Prefix}) } // LoginCallback is called by Dial to get the username and password for a SFTP connection. @@ -248,9 +248,6 @@ func (f *fileSystem) ID() (string, error) { } func (f *fileSystem) Prefix() string { - if f.prefix == "" { - return Prefix - } return f.prefix } @@ -263,20 +260,26 @@ func (f *fileSystem) String() string { } func (*fileSystem) URL(cleanPath string) string { + // Prefix was trimmed from cleanPath in JoinCleanPath return Prefix + cleanPath } -func (f *fileSystem) JoinCleanFile(uriParts ...string) fs.File { - println("sftpfs.JoinCleanFile", f.prefix, f.JoinCleanPath(uriParts...)) - return fs.File(f.prefix + f.JoinCleanPath(uriParts...)) -} - func (*fileSystem) JoinCleanPath(uriParts ...string) string { return fsimpl.JoinCleanPath(uriParts, Prefix, Separator) } +func (f *fileSystem) JoinCleanFile(uriParts ...string) fs.File { + path := f.JoinCleanPath(uriParts...) + if strings.HasSuffix(f.prefix, Separator) && strings.HasPrefix(path, Separator) { + // For example: "sftp://" + "/example.com/absolute/path" + // should not result in "sftp:///example.com/absolute/path" + path = path[len(Separator):] + } + return fs.File(f.prefix + path) +} + func (f *fileSystem) SplitPath(filePath string) []string { - return fsimpl.SplitPath(filePath, f.Prefix(), Separator) + return fsimpl.SplitPath(filePath, f.prefix, Separator) } func (f *fileSystem) Separator() string { return Separator }