89 lines
2.3 KiB
Go
89 lines
2.3 KiB
Go
package drive
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"os/exec"
|
|
"path/filepath"
|
|
"strings"
|
|
)
|
|
|
|
const binaryName = "proton-drive"
|
|
|
|
// Lookup returns the full path to the proton-drive binary in PATH.
|
|
func Lookup() (string, error) {
|
|
return exec.LookPath(binaryName)
|
|
}
|
|
|
|
// CheckAuth verifies that the user is authenticated by listing /my-files.
|
|
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
|
|
}
|
|
|
|
// Upload uploads localPath to remotePath on Proton Drive.
|
|
// remotePath is a full path including filename (e.g. /my-files/md/report.md).
|
|
// The CLI uploads to a parent directory and preserves the local filename,
|
|
// so if the remote filename differs from the local one, a temp copy is staged.
|
|
// Existing remote files are overwritten (--conflict-strategy replace).
|
|
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,
|
|
"--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)
|
|
}
|