fix(import): name merged parts after their folder and clean up empty ones
This commit is contained in:
+5
-1
@@ -816,7 +816,11 @@ $("#import-merge").addEventListener("click", () => {
|
|||||||
toast("Die Einträge liegen in verschiedenen Ordnern", true);
|
toast("Die Einträge liegen in verschiedenen Ordnern", true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const name = commonPrefix(chosen.map((it) => it.name)) || chosen[0].name;
|
// parts may share no prefix at all ("A - Sphinx", "B - Volk"): then the
|
||||||
|
// folder holding them carries the real title ("100 - Toteninsel")
|
||||||
|
const parentName = (chosen[0].rel_dir || "").split("/").filter(Boolean).pop();
|
||||||
|
const name =
|
||||||
|
commonPrefix(chosen.map((it) => it.name)) || parentName || chosen[0].name;
|
||||||
const merged = {
|
const merged = {
|
||||||
path: chosen[0].path.slice(0, chosen[0].path.length - chosen[0].name.length - 1) || chosen[0].path,
|
path: chosen[0].path.slice(0, chosen[0].path.length - chosen[0].name.length - 1) || chosen[0].path,
|
||||||
name,
|
name,
|
||||||
|
|||||||
@@ -504,3 +504,37 @@ def test_merge_at_download_root_keeps_the_download_dir(client):
|
|||||||
assert res["ok"], res
|
assert res["ok"], res
|
||||||
assert client.downloads.is_dir()
|
assert client.downloads.is_dir()
|
||||||
assert not (client.downloads / "Teil 1").exists()
|
assert not (client.downloads / "Teil 1").exists()
|
||||||
|
|
||||||
|
|
||||||
|
def test_merged_parts_clean_up_nested_source_folders(client):
|
||||||
|
""""100 - Toteninsel/A - Sphinx/CD/*.mp3" - every emptied level below the
|
||||||
|
merged item goes away, the cover folder keeps its parent alive."""
|
||||||
|
lib_id = client.post("/api/libraries", json={
|
||||||
|
"name": "L", "media_type": "audiobook", "root_path": str(client.tmp_path / "l"),
|
||||||
|
"folder_template": "{Title}", "file_template": "{Title}",
|
||||||
|
}).json()["id"]
|
||||||
|
req_id = client.post("/api/requests",
|
||||||
|
json={"library_id": lib_id, "title": "Toteninsel"}).json()["id"]
|
||||||
|
|
||||||
|
base = client.downloads / "100 - Toteninsel"
|
||||||
|
files = []
|
||||||
|
for part in ("A - Sphinx", "B - Volk", "C - Graeber"):
|
||||||
|
cd = base / part / "CD"
|
||||||
|
cd.mkdir(parents=True)
|
||||||
|
for i in (1, 2):
|
||||||
|
f = cd / f"{i:02d}.mp3"
|
||||||
|
f.write_bytes(b"")
|
||||||
|
files.append(str(f))
|
||||||
|
(base / "Cover").mkdir()
|
||||||
|
(base / "Cover" / "front.jpg").write_bytes(b"")
|
||||||
|
|
||||||
|
res = client.post("/api/import", json={"items": [{
|
||||||
|
"path": str(base), "is_dir": True, "files": files, "request_id": req_id,
|
||||||
|
}]}).json()["results"][0]
|
||||||
|
assert res["ok"], res
|
||||||
|
assert sorted(p.name for p in Path(res["dest"]).iterdir()) == [
|
||||||
|
f"Toteninsel - Part 0{i}.mp3" for i in range(1, 7)
|
||||||
|
]
|
||||||
|
assert not (base / "A - Sphinx").exists()
|
||||||
|
assert not (base / "B - Volk").exists()
|
||||||
|
assert (base / "Cover" / "front.jpg").exists()
|
||||||
|
|||||||
@@ -27,10 +27,17 @@ def import_item(item_path: str, files: list[str], is_dir: bool, request, library
|
|||||||
# files (cover art, booklets) is left alone.
|
# files (cover art, booklets) is left alone.
|
||||||
src_dir = Path(item_path)
|
src_dir = Path(item_path)
|
||||||
download_root = Path(config.DOWNLOAD_DIR).resolve()
|
download_root = Path(config.DOWNLOAD_DIR).resolve()
|
||||||
candidates = {src_dir} | {p.parent for p in paths}
|
# collect every folder the files came from, up to (and including) the
|
||||||
|
# item itself - "…/100 - Toteninsel/A - Sphinx/CD" contributes all three
|
||||||
|
candidates = {src_dir}
|
||||||
|
for p in paths:
|
||||||
|
d = p.parent
|
||||||
|
while d == src_dir or src_dir in d.parents:
|
||||||
|
candidates.add(d)
|
||||||
|
if d == src_dir:
|
||||||
|
break
|
||||||
|
d = d.parent
|
||||||
for d in sorted(candidates, key=lambda p: len(p.parts), reverse=True):
|
for d in sorted(candidates, key=lambda p: len(p.parts), reverse=True):
|
||||||
if d != src_dir and src_dir not in d.parents:
|
|
||||||
continue # never touch anything outside the item
|
|
||||||
if d.resolve() == download_root:
|
if d.resolve() == download_root:
|
||||||
continue # merged items can point at the download dir itself
|
continue # merged items can point at the download dir itself
|
||||||
if d.is_dir() and not any(f.is_file() for f in d.rglob("*")):
|
if d.is_dir() and not any(f.is_file() for f in d.rglob("*")):
|
||||||
|
|||||||
Reference in New Issue
Block a user