73 lines
1.6 KiB
Go
73 lines
1.6 KiB
Go
package vault
|
|
|
|
import (
|
|
"errors"
|
|
"io/fs"
|
|
"os"
|
|
"path/filepath"
|
|
)
|
|
|
|
// SeedExamples populates only a completely unused vault, before the watcher starts.
|
|
// Existing folders, hidden files, icons, or recycled notes count as user data.
|
|
func (v *Vault) SeedExamples(examples fs.FS) (err error) {
|
|
v.mu.Lock()
|
|
defer v.mu.Unlock()
|
|
|
|
entries, err := os.ReadDir(v.root)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
for _, entry := range entries {
|
|
if entry.Name() != metaDir || !entry.IsDir() {
|
|
return nil
|
|
}
|
|
}
|
|
metadata, err := os.ReadDir(filepath.Join(v.root, metaDir))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
for _, entry := range metadata {
|
|
if entry.Name() != "trash" || !entry.IsDir() {
|
|
return nil
|
|
}
|
|
}
|
|
trash, err := os.ReadDir(v.trash)
|
|
if err != nil || len(trash) != 0 {
|
|
return err
|
|
}
|
|
|
|
stage, err := os.MkdirTemp(v.root, tmpPrefix+"examples-")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
cleanup := true
|
|
defer func() {
|
|
if cleanup {
|
|
err = errors.Join(err, os.RemoveAll(stage))
|
|
}
|
|
}()
|
|
if err = os.CopyFS(stage, examples); err != nil {
|
|
return err
|
|
}
|
|
entries, err = os.ReadDir(stage)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
var published []string
|
|
for _, entry := range entries {
|
|
name := entry.Name()
|
|
if err = os.Rename(filepath.Join(stage, name), filepath.Join(v.root, name)); err != nil {
|
|
for _, previous := range published {
|
|
if rollback := os.Rename(filepath.Join(v.root, previous), filepath.Join(stage, previous)); rollback != nil {
|
|
// Preserve the staging directory if it contains the only copy of any files.
|
|
cleanup = false
|
|
err = errors.Join(err, rollback)
|
|
}
|
|
}
|
|
return err
|
|
}
|
|
published = append(published, name)
|
|
}
|
|
return nil
|
|
}
|