feat: add ftp root path setting
This commit is contained in:
@@ -40,9 +40,9 @@ type CaptureAndFTPService struct {
|
||||
Cfg domain.FTPConfig
|
||||
}
|
||||
|
||||
// ExecuteWithBytes uploads previously captured PNG bytes and copies the exact
|
||||
// remote path semantics shown in Settings: FTP paths are rooted at "/", while
|
||||
// SFTP paths are relative to the authenticated user's home directory.
|
||||
// ExecuteWithBytes uploads previously captured PNG bytes and copies a display
|
||||
// path built from the configured root directory plus the uploaded relative
|
||||
// path. RootDirectory deliberately does not affect the upload destination.
|
||||
func (s *CaptureAndFTPService) ExecuteWithBytes(ctx context.Context, pngBytes []byte) error {
|
||||
if s.Uploader == nil {
|
||||
s.notifyFailure("FTP/SFTP not configured")
|
||||
@@ -80,7 +80,7 @@ func (s *CaptureAndFTPService) ExecuteWithBytes(ctx context.Context, pngBytes []
|
||||
return err
|
||||
}
|
||||
|
||||
clipText := ftpShareText(protocol, relPath)
|
||||
clipText := ftpShareText(protocol, s.Cfg.RootDirectory, relPath)
|
||||
if s.Clipboard != nil {
|
||||
if err := s.Clipboard.WriteText(clipText); err != nil {
|
||||
s.notifyFailure("clipboard write failed: " + err.Error())
|
||||
@@ -131,11 +131,16 @@ func normalizedFTPProtocol(protocol string) string {
|
||||
return domain.FTPProtocolFTP
|
||||
}
|
||||
|
||||
func ftpShareText(protocol, relPath string) string {
|
||||
if protocol == domain.FTPProtocolSFTP {
|
||||
return "~/" + relPath
|
||||
func ftpShareText(protocol, rootDirectory, relPath string) string {
|
||||
rootDirectory = strings.TrimSpace(rootDirectory)
|
||||
if rootDirectory == "" {
|
||||
if protocol == domain.FTPProtocolSFTP {
|
||||
rootDirectory = "~/"
|
||||
} else {
|
||||
rootDirectory = "/"
|
||||
}
|
||||
}
|
||||
return "/" + relPath
|
||||
return strings.TrimRight(rootDirectory, "/") + "/" + strings.TrimLeft(relPath, "/")
|
||||
}
|
||||
|
||||
func (s *CaptureAndFTPService) notifyFailure(reason string) {
|
||||
|
||||
@@ -52,23 +52,52 @@ func TestCaptureAndFTPServiceUploadsAndCopiesFTPPath(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestCaptureAndFTPServiceCopiesSFTPHomePath(t *testing.T) {
|
||||
func TestCaptureAndFTPServiceCopiesConfiguredRootPath(t *testing.T) {
|
||||
uploader := &fakeFTPUploader{}
|
||||
clip := &fakeClipboard{}
|
||||
svc := &CaptureAndFTPService{
|
||||
Uploader: uploader,
|
||||
Clipboard: clip,
|
||||
Cfg: domain.FTPConfig{
|
||||
Protocol: domain.FTPProtocolSFTP,
|
||||
PathPrefix: "images",
|
||||
Protocol: domain.FTPProtocolSFTP,
|
||||
RootDirectory: "~/ftp/",
|
||||
PathPrefix: "images",
|
||||
},
|
||||
}
|
||||
|
||||
if err := svc.ExecuteWithBytes(context.Background(), []byte("png")); err != nil {
|
||||
t.Fatalf("upload SFTP screenshot: %v", err)
|
||||
}
|
||||
if clip.text != "~/"+uploader.path {
|
||||
t.Fatalf("expected SFTP home path copied, got %q", clip.text)
|
||||
if clip.text != "~/ftp/"+uploader.path {
|
||||
t.Fatalf("expected configured SFTP root path copied, got %q", clip.text)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFTPShareTextJoinsConfiguredRootAndRemoteDirectory(t *testing.T) {
|
||||
const relPath = "snapgo/2026/07/20260713-110413-18lnbx.png"
|
||||
const want = "~/ftp/snapgo/2026/07/20260713-110413-18lnbx.png"
|
||||
if got := ftpShareText(domain.FTPProtocolSFTP, "~/ftp/", relPath); got != want {
|
||||
t.Fatalf("ftpShareText() = %q, want %q", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFTPShareTextUsesProtocolDefaultWhenRootDirectoryIsEmpty(t *testing.T) {
|
||||
const relPath = "snapgo/2026/07/image.png"
|
||||
tests := []struct {
|
||||
name string
|
||||
protocol string
|
||||
want string
|
||||
}{
|
||||
{name: "FTP", protocol: domain.FTPProtocolFTP, want: "/" + relPath},
|
||||
{name: "SFTP", protocol: domain.FTPProtocolSFTP, want: "~/" + relPath},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := ftpShareText(tt.protocol, "", relPath); got != tt.want {
|
||||
t.Fatalf("ftpShareText() = %q, want %q", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user