Go back to the hardlink deduplicator (1da0132), keeping backups
Restores the code of 1da0132 ("Add a setting to hide the quarantine from
Plex") and removes everything added after it: the tag editor, album art,
organizing/naming, the step-by-step tune-up and library types.
Kept:
- Database backups (Settings -> Backups): scheduled, manual, download,
restore, and the optional backup before every action.
- The .env-driven docker-compose.yml for Arcane.
Databases that already ran the later migrations keep working: migrations
6-10 stay in the list (they only add columns) so numbering never goes
backwards, and Undo refuses History entries of removed features instead
of treating them as links.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
7b180e26db
commit
e0617047f7
44 files changed
+103
-10456
No files matched your search
+7
-62
@@ -621,52 +621,17 @@ func (e *Engine) Undo(ctx context.Context, opID int64) error {
|
||||
if o.PurgedAt != nil {
|
||||
return errors.New("the quarantined original was already purged")
|
||||
}
|
||||
switch o.Action {
|
||||
case store.ActLink, store.ActPromote, store.ActBuild, store.ActRemove, store.ActRename:
|
||||
default:
|
||||
// History can hold operations of features that were removed (tag
|
||||
// edits, file moves); undoing them as a link would be wrong.
|
||||
return fmt.Errorf("%q operations can no longer be undone from playlink; their originals stay in the quarantine folder", o.Action)
|
||||
}
|
||||
l, err := e.loadPair(ctx, o.PairID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if o.Action == store.ActCover {
|
||||
if err := e.undoCover(l, o); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := e.st.MarkUndone(ctx, o.ID); err != nil {
|
||||
return err
|
||||
}
|
||||
e.log.Info("folder cover undone", "op", o.ID)
|
||||
return nil
|
||||
}
|
||||
if o.Action == store.ActMoveDir {
|
||||
if err := undoMoveDir(l, o); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := e.st.MarkUndone(ctx, o.ID); err != nil {
|
||||
return err
|
||||
}
|
||||
e.log.Info("folder move undone", "op", o.ID, "folder", o.RelNew)
|
||||
_, _ = e.StartScan(o.PairID, "undo")
|
||||
return nil
|
||||
}
|
||||
if o.Action == store.ActMove {
|
||||
if err := undoMove(l, o); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := e.st.MarkUndone(ctx, o.ID); err != nil {
|
||||
return err
|
||||
}
|
||||
e.log.Info("file move undone", "op", o.ID)
|
||||
_, _ = e.StartScan(o.PairID, "undo")
|
||||
return nil
|
||||
}
|
||||
if o.Action == store.ActTags {
|
||||
if err := e.undoTags(ctx, l, o); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := e.st.MarkUndone(ctx, o.ID); err != nil {
|
||||
return err
|
||||
}
|
||||
e.log.Info("tag edit undone", "op", o.ID)
|
||||
return nil
|
||||
}
|
||||
if o.Action == store.ActRename {
|
||||
if err := undoRename(l, o); err != nil {
|
||||
return err
|
||||
@@ -890,26 +855,6 @@ func (e *Engine) Recover(ctx context.Context) {
|
||||
return
|
||||
}
|
||||
for _, o := range ops {
|
||||
if o.Action == store.ActMoveDir {
|
||||
if l, err := e.loadPair(ctx, o.PairID); err == nil {
|
||||
recoverMoveDir(l, o, e.log)
|
||||
}
|
||||
_ = e.st.FinishOp(ctx, o.ID, store.OpInterrupted, "interrupted by shutdown; rescan to verify state")
|
||||
continue
|
||||
}
|
||||
if o.Action == store.ActMove {
|
||||
if l, err := e.loadPair(ctx, o.PairID); err == nil {
|
||||
recoverMove(l, o)
|
||||
}
|
||||
_ = e.st.FinishOp(ctx, o.ID, store.OpInterrupted, "interrupted by shutdown; rescan to verify state")
|
||||
continue
|
||||
}
|
||||
if o.Action == store.ActTags {
|
||||
msg := e.recoverTags(ctx, o)
|
||||
_ = e.st.FinishOp(ctx, o.ID, store.OpInterrupted, msg)
|
||||
e.log.Warn("recovered interrupted tag edit", "op", o.ID, "result", msg)
|
||||
continue
|
||||
}
|
||||
if o.Action == store.ActRename {
|
||||
if p, err := e.st.Pair(ctx, o.PairID); err == nil {
|
||||
recoverRename(p, o, e.log)
|
||||
|
||||
Reference in new issue
Block a user