Files
dirmd/internal/drive/drive.go
T

139 lines
3.1 KiB
Go

package drive
import (
"fmt"
"os"
"os/exec"
"path/filepath"
"strings"
)
const binaryName = "proton-drive"
func Lookup() (string, error) {
return exec.LookPath(binaryName)
}
func CheckAuth() error {
binary, err := Lookup()
if err != nil {
return fmt.Errorf("proton-drive not found in PATH: %w", err)
}
cmd := exec.Command(binary, "filesystem", "list", "/my-files")
cmd.Stdout = nil
cmd.Stderr = nil
if err := cmd.Run(); err != nil {
return fmt.Errorf("not authenticated with proton-drive (run 'proton-drive auth login'): %w", err)
}
return nil
}
func EnsureRemoteParent(remoteDir string) error {
binary, err := Lookup()
if err != nil {
return fmt.Errorf("proton-drive not found in PATH: %w", err)
}
parentDir := filepath.Dir(remoteDir)
grandparent := filepath.Dir(parentDir)
parentName := filepath.Base(parentDir)
cmd := exec.Command(binary, "filesystem", "create-folder", grandparent, parentName)
cmd.Stdout = nil
cmd.Stderr = nil
cmd.Run()
return nil
}
func CleanRemote(remoteDir string) {
binary, err := Lookup()
if err != nil {
return
}
cmd := exec.Command(binary, "filesystem", "delete", remoteDir)
cmd.Stdout = nil
cmd.Stderr = nil
cmd.Run()
}
func UploadDir(localDir, remoteDir string) error {
binary, err := Lookup()
if err != nil {
return fmt.Errorf("proton-drive not found in PATH: %w", err)
}
if err := EnsureRemoteParent(remoteDir); err != nil {
return fmt.Errorf("cannot prepare remote directory: %w", err)
}
CleanRemote(remoteDir)
remoteParent := filepath.Dir(remoteDir)
cmd := exec.Command(binary, "filesystem", "upload", localDir, remoteParent,
"--folder-conflict-strategy", "replace", "--file-conflict-strategy", "replace")
var stderr strings.Builder
cmd.Stderr = &stderr
if err := cmd.Run(); err != nil {
return fmt.Errorf("upload to proton-drive failed: %w: %s",
err, strings.TrimSpace(stderr.String()))
}
return nil
}
func Upload(localPath, remotePath string) error {
binary, err := Lookup()
if err != nil {
return fmt.Errorf("proton-drive not found in PATH: %w", err)
}
remoteDir := filepath.Dir(remotePath)
remoteName := filepath.Base(remotePath)
localName := filepath.Base(localPath)
if remoteName == localName {
return runUpload(binary, localPath, remoteDir)
}
tmpDir, err := os.MkdirTemp("", "dirmd-upload-*")
if err != nil {
return fmt.Errorf("cannot create temp dir: %w", err)
}
defer os.RemoveAll(tmpDir)
tmpFile := filepath.Join(tmpDir, remoteName)
if err := copyFile(localPath, tmpFile); err != nil {
return fmt.Errorf("cannot stage temp file: %w", err)
}
return runUpload(binary, tmpFile, remoteDir)
}
func runUpload(binary, localPath, remoteDir string) error {
cmd := exec.Command(binary, "filesystem", "upload", localPath, remoteDir,
"--folder-conflict-strategy", "replace", "--file-conflict-strategy", "replace")
var stderr strings.Builder
cmd.Stderr = &stderr
if err := cmd.Run(); err != nil {
return fmt.Errorf("upload to proton-drive failed: %w: %s",
err, strings.TrimSpace(stderr.String()))
}
return nil
}
func copyFile(src, dst string) error {
data, err := os.ReadFile(src)
if err != nil {
return err
}
return os.WriteFile(dst, data, 0644)
}