fixed correct proton drive upload with vertical slices

This commit is contained in:
Bartal Laearsson
2026-08-08 13:45:04 +01:00
parent b60588c4a0
commit a483371dc5
3 changed files with 124 additions and 55 deletions
+51 -7
View File
@@ -10,12 +10,10 @@ import (
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 {
@@ -32,11 +30,57 @@ func CheckAuth() error {
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).
// EnsureRemoteParent creates the parent remote directory if it doesn't exist.
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)
// Try create-folder on the grandparent for the parent
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() // Ignore errors — folder may already exist
return nil
}
// UploadDir uploads an entire local directory to Proton Drive.
// The local directory's basename becomes the remote directory name.
func UploadDir(localDir, remoteDir string) error {
binary, err := Lookup()
if err != nil {
return fmt.Errorf("proton-drive not found in PATH: %w", err)
}
// Ensure parent of remote dir exists
if err := EnsureRemoteParent(remoteDir); err != nil {
return fmt.Errorf("cannot prepare remote directory: %w", err)
}
// Upload to parent — the local dir's basename creates the remote dir
remoteParent := filepath.Dir(remoteDir)
cmd := exec.Command(binary, "filesystem", "upload", localDir, remoteParent,
"--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
}
// Upload uploads a single local file to a remote path on Proton Drive.
func Upload(localPath, remotePath string) error {
binary, err := Lookup()
if err != nil {
+15 -12
View File
@@ -84,7 +84,7 @@ func Write(result *walker.Result, outputPath string, appendMode bool, singleFile
// WriteSlices generates a root markdown file plus one markdown per top-level directory.
// Returns the list of generated file paths.
func WriteSlices(result *walker.Result, outputPath string) ([]string, error) {
func WriteSlices(result *walker.Result, outputDir string) ([]string, error) {
entries := result.Entries
if len(entries) == 0 {
return nil, fmt.Errorf("no entries to write")
@@ -107,15 +107,13 @@ func WriteSlices(result *walker.Result, outputPath string) ([]string, error) {
}
}
outDir := filepath.Dir(outputPath)
var generated []string
// Write root file
rootPath := outputPath
// Write root file as index.md
rootPath := filepath.Join(outputDir, "index.md")
generated = append(generated, rootPath)
if err := writeRootSlice(rootPath, absRoot, rootName, rootFiles, topLevelDirs, outDir); err != nil {
if err := writeRootSlice(rootPath, absRoot, rootName, rootFiles, topLevelDirs); err != nil {
return nil, fmt.Errorf("failed to write root slice: %w", err)
}
@@ -128,7 +126,7 @@ func WriteSlices(result *walker.Result, outputPath string) ([]string, error) {
for _, dirName := range dirNames {
sliceName := strings.TrimSuffix(dirName, "/") + ".md"
sliceDir := filepath.Join(outDir, dirName)
sliceDir := filepath.Join(outputDir, dirName)
if err := os.MkdirAll(sliceDir, 0755); err != nil {
return nil, fmt.Errorf("cannot create slice directory %s: %w", sliceDir, err)
}
@@ -141,13 +139,18 @@ func WriteSlices(result *walker.Result, outputPath string) ([]string, error) {
// Strip dirName prefix for tree building only
treeEntries := make([]walker.Entry, len(dirEntries))
for i, e := range dirEntries {
treeEntries[i] = walker.Entry{
RelPath: strings.TrimPrefix(e.RelPath, dirName+string(filepath.Separator)),
Size: e.Size,
sepIdx := strings.Index(e.RelPath, string(filepath.Separator))
if sepIdx >= 0 {
treeEntries[i] = walker.Entry{
RelPath: e.RelPath[sepIdx+1:],
Size: e.Size,
}
} else {
treeEntries[i] = e
}
}
if err := writeDirSlice(slicePath, absDir, absRoot, dirName, treeEntries, dirEntries, filepath.Base(outputPath)); err != nil {
if err := writeDirSlice(slicePath, absDir, absRoot, dirName, treeEntries, dirEntries, "index.md"); err != nil {
return nil, fmt.Errorf("failed to write slice %s: %w", sliceName, err)
}
}
@@ -155,7 +158,7 @@ func WriteSlices(result *walker.Result, outputPath string) ([]string, error) {
return generated, nil
}
func writeRootSlice(path, absRoot, rootName string, rootFiles []walker.Entry, topLevelDirs map[string][]walker.Entry, outDir string) error {
func writeRootSlice(path, absRoot, rootName string, rootFiles []walker.Entry, topLevelDirs map[string][]walker.Entry) error {
f, err := os.Create(path)
if err != nil {
return fmt.Errorf("cannot create root file: %w", err)