Files
backy/pkg/backy/file.go
Andrew Woodlee 765ef2ee36
All checks were successful
ci/woodpecker/push/publish-docs Pipeline was successful
ci/woodpecker/tag/gitea Pipeline was successful
ci/woodpecker/tag/publish-docs Pipeline was successful
ci/woodpecker/release/publish-docs Pipeline was successful
v0.11.3
2026-01-31 01:06:18 -06:00

194 lines
3.7 KiB
Go

package backy
import (
"fmt"
"io/fs"
"os"
"github.com/pkg/sftp"
"golang.org/x/crypto/ssh"
)
type LocalFileCommandExecutor struct{}
func (f *LocalFileCommandExecutor) Execute(cmd *Command) error {
localExecutor := LocalCommandExecutor{}
switch cmd.FileOperation {
case "copy":
return localExecutor.copyFile(cmd.Source, cmd.Destination, cmd.Permissions)
default:
return fmt.Errorf("unsupported file operation: %s", cmd.FileOperation)
}
}
func (f *LocalFileCommandExecutor) ReadLocalFile(path string) ([]byte, error) {
data, err := os.ReadFile(path)
if err != nil {
return nil, err
}
return data, nil
}
func (f *LocalFileCommandExecutor) WriteLocalFile(path string, data []byte, Perms fs.FileMode) error {
err := os.WriteFile(path, data, Perms)
if err != nil {
return err
}
return nil
}
func (f *LocalCommandExecutor) copyFile(source, destination string, Perms fs.FileMode) error {
input, err := os.ReadFile(source)
if err != nil {
return err
}
err = os.WriteFile(destination, input, Perms)
if err != nil {
return err
}
return nil
}
type RemoteFileCommandExecutor struct{}
func (r *RemoteFileCommandExecutor) Execute(cmd *Command) error {
remoteExecutor := RemoteFileCommandExecutor{}
sourceTypeLocal := false
if cmd.SourceType == "local" {
sourceTypeLocal = true
}
switch cmd.FileOperation {
case "copy":
return remoteExecutor.copyFile(cmd.Source, cmd.Destination, cmd.Permissions, cmd.RemoteHost.SshClient, sourceTypeLocal)
default:
return fmt.Errorf("unsupported file operation: %s", cmd.FileOperation)
}
}
func (r *RemoteFileCommandExecutor) copyFile(source, destination string, Perms fs.FileMode, sshClient *ssh.Client, sourceTypeLocal bool) error {
if sourceTypeLocal {
input, err := os.ReadFile(source)
if err != nil {
return err
}
sftpClient, sftpErr := sftp.NewClient(sshClient)
if sftpErr != nil {
return sftpErr
}
defer sftpClient.Close()
destFile, err := sftpClient.Create(destination)
if err != nil {
return err
}
defer destFile.Close()
_, err = destFile.Write(input)
if err != nil {
return err
}
err = destFile.Chmod(Perms)
if err != nil {
return err
}
return nil
}
client, err := sftp.NewClient(sshClient)
if err != nil {
return err
}
srcFile, err := client.Open(source)
if err != nil {
return err
}
defer srcFile.Close()
destFile, err := client.Create(destination)
if err != nil {
return err
}
defer destFile.Close()
_, err = srcFile.WriteTo(destFile)
if err != nil {
return err
}
err = destFile.Chmod(Perms)
if err != nil {
return err
}
return nil
}
func (r *RemoteFileCommandExecutor) ReadRemoteFile(path string, sshClient *ssh.Client) ([]byte, error) {
sftpClient, sftpErr := sftp.NewClient(sshClient)
if sftpErr != nil {
return nil, sftpErr
}
defer sftpClient.Close()
file, err := sftpClient.Open(path)
if err != nil {
return nil, err
}
defer file.Close()
var fileData []byte
_, err = file.Read(fileData)
if err != nil {
return nil, err
}
return fileData, nil
}
func (r *RemoteFileCommandExecutor) WriteRemoteFile(path string, data []byte, Perms fs.FileMode, sshClient *ssh.Client) error {
sftpClient, sftpErr := sftp.NewClient(sshClient)
if sftpErr != nil {
return sftpErr
}
defer sftpClient.Close()
file, err := sftpClient.Create(path)
if err != nil {
return err
}
defer file.Close()
_, err = file.Write(data)
if err != nil {
return err
}
err = file.Chmod(Perms)
if err != nil {
return err
}
return nil
}
type FileCommandExecutor interface {
Execute(cmd *Command) error
}
func NewFileCommandExecutor(isRemote bool) FileCommandExecutor {
if isRemote {
return &RemoteFileCommandExecutor{}
}
return &LocalFileCommandExecutor{}
}