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
@@ -403,70 +403,3 @@ func CopyReplace(src, dst string, mode fs.FileMode) error {
|
||||
func MkdirAllLike(dir string) error {
|
||||
return os.MkdirAll(dir, 0o775)
|
||||
}
|
||||
|
||||
// CopyNew copies src to dst, which must not exist. The copy is fsynced and
|
||||
// verified byte for byte. Used for backups that must not share an inode with
|
||||
// the original (the original is about to be modified in place).
|
||||
func CopyNew(src, dst string, mode fs.FileMode) error {
|
||||
in, err := os.Open(src)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer in.Close()
|
||||
out, err := os.OpenFile(dst, os.O_WRONLY|os.O_CREATE|os.O_EXCL, mode.Perm())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fail := func(e error) error { out.Close(); _ = os.Remove(dst); return e }
|
||||
if _, err := io.Copy(out, in); err != nil {
|
||||
return fail(err)
|
||||
}
|
||||
if err := out.Sync(); err != nil {
|
||||
return fail(err)
|
||||
}
|
||||
if err := out.Close(); err != nil {
|
||||
_ = os.Remove(dst)
|
||||
return err
|
||||
}
|
||||
if same, err := SameContent(src, dst); err != nil || !same {
|
||||
_ = os.Remove(dst)
|
||||
if err == nil {
|
||||
err = fmt.Errorf("%w: backup differs from the original", ErrVerifyFailed)
|
||||
}
|
||||
return err
|
||||
}
|
||||
return SyncDir(filepath.Dir(dst))
|
||||
}
|
||||
|
||||
// OverwriteInPlace replaces the contents of dst with the bytes of src while
|
||||
// keeping dst's inode, so every hardlink of dst sees the new contents. This is
|
||||
// not atomic: callers keep a backup (CopyNew) to restore from on failure.
|
||||
func OverwriteInPlace(dst, src string) error {
|
||||
in, err := os.Open(src)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer in.Close()
|
||||
out, err := os.OpenFile(dst, os.O_WRONLY|os.O_TRUNC, 0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := io.Copy(out, in); err != nil {
|
||||
out.Close()
|
||||
return err
|
||||
}
|
||||
if err := out.Sync(); err != nil {
|
||||
out.Close()
|
||||
return err
|
||||
}
|
||||
if err := out.Close(); err != nil {
|
||||
return err
|
||||
}
|
||||
if same, err := SameContent(src, dst); err != nil || !same {
|
||||
if err == nil {
|
||||
err = fmt.Errorf("%w: file does not match what was written", ErrVerifyFailed)
|
||||
}
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
Reference in new issue
Block a user