50 lines
2.0 KiB
Python
50 lines
2.0 KiB
Python
#!/usr/bin/env python3
|
|
"""prune: list or remove stems whose song is no longer in the music library.
|
|
|
|
prune.py dry run: print orphans (song gone) and changed (song replaced)
|
|
prune.py --apply remove the orphans
|
|
prune.py --apply --changed also remove stems of replaced songs, so stemd redoes them
|
|
|
|
MUSIC_DIR and STEMS_DIR as for stemd. Refuses when the music folder holds no tracks.
|
|
Without --force it also refuses to remove more than 20% of the stems in one go.
|
|
"""
|
|
|
|
import argparse
|
|
import os
|
|
import sys
|
|
|
|
_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
|
sys.path.insert(0, os.path.join(_ROOT, "desktop"))
|
|
sys.path.insert(0, _ROOT)
|
|
|
|
from stemify.library_core import find_stale, iter_tracks, remove_stems # noqa: E402
|
|
|
|
|
|
def main():
|
|
ap = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter)
|
|
ap.add_argument("--music", default=os.environ.get("MUSIC_DIR", "/music"))
|
|
ap.add_argument("--stems", default=os.environ.get("STEMS_DIR", "/stems"))
|
|
ap.add_argument("--apply", action="store_true")
|
|
ap.add_argument("--changed", action="store_true")
|
|
ap.add_argument("--force", action="store_true")
|
|
a = ap.parse_args()
|
|
total = sum(1 for _ in iter_tracks(a.music, a.stems))
|
|
if not total:
|
|
sys.exit(f"no tracks in {a.music}; is the share mounted?")
|
|
orphans, changed = find_stale(a.music, a.stems)
|
|
drop = orphans + (changed if a.changed else [])
|
|
for label, items in (("orphan", orphans), ("changed", changed)):
|
|
for p in items:
|
|
print(f"{label}\t{os.path.relpath(p, a.stems)}")
|
|
print(f"{len(orphans)} orphans, {len(changed)} changed, {total} tracks in the library")
|
|
if not a.apply or not drop:
|
|
return
|
|
if len(drop) > 0.2 * (total + len(orphans)) and not a.force:
|
|
sys.exit("that is over 20% of the stems; check the paths or pass --force")
|
|
remove_stems(a.stems, drop)
|
|
print(f"removed {len(drop)}")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|