fix(trash): retain metadata when permanent deletion fails
This commit is contained in:
1 parent
56145dba72
commit
9aaaf15278
3 files changed
+119
-5
No files matched your search
+32
-3
@@ -1,12 +1,41 @@
|
||||
package vault
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"time"
|
||||
)
|
||||
|
||||
// 调用方持有写锁并已读取验证元数据。先删除内容,失败时保留条目的管理依据。
|
||||
func (v *Vault) purgeTrashItemLocked(metadata trashMetadata) error {
|
||||
dir := filepath.Join(v.trash, metadata.ID)
|
||||
entries, err := os.ReadDir(dir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, entry := range entries {
|
||||
if entry.Name() == "meta.json" {
|
||||
continue
|
||||
}
|
||||
if err := os.RemoveAll(filepath.Join(dir, entry.Name())); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
metaPath := filepath.Join(dir, "meta.json")
|
||||
if err := os.Remove(metaPath); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := os.Remove(dir); err != nil {
|
||||
// 父目录不可写等原因仍可能阻止最后的 rmdir,恢复元数据以便继续清理。
|
||||
data, _ := json.Marshal(metadata)
|
||||
return errors.Join(err, atomicWrite(metaPath, data))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type TrashFailure struct {
|
||||
ID string `json:"id"`
|
||||
Error string `json:"error"`
|
||||
@@ -35,12 +64,12 @@ func (v *Vault) PurgeTrash(days int64, now time.Time) (TrashPurgeResult, error)
|
||||
if !trashIDPattern.MatchString(id) {
|
||||
continue // 不删除非本程序管理的文件。
|
||||
}
|
||||
item, err := v.readTrashItem(id)
|
||||
if err == nil && days > 0 && (item.DeletedAt > now.UnixMilli() || (now.UnixMilli()-item.DeletedAt)/int64(24*time.Hour/time.Millisecond) < days) {
|
||||
metadata, err := v.readTrashMetadata(id)
|
||||
if err == nil && days > 0 && (metadata.DeletedAt > now.UnixMilli() || (now.UnixMilli()-metadata.DeletedAt)/int64(24*time.Hour/time.Millisecond) < days) {
|
||||
continue
|
||||
}
|
||||
if err == nil {
|
||||
err = os.RemoveAll(filepath.Join(v.trash, id))
|
||||
err = v.purgeTrashItemLocked(metadata)
|
||||
}
|
||||
if err != nil {
|
||||
result.Failed = append(result.Failed, TrashFailure{ID: id, Error: err.Error()})
|
||||
|
||||
Reference in new issue
Block a user