fix: cut long names from the middle, not the end
Build and publish container / build (pull_request) Canceled after 1m18s
Build and publish container / build (pull_request) Canceled after 1m18s
The shortening fitted the path and destroyed its meaning. Lidarr writes "Artist - Album - 07 - Flamethrower.mp3" inside a directory already named for that artist and album, so a long album title occurs three times in one path and everything that distinguishes one track from another sits at the very end. Cutting from the end removed precisely that: King Gizzard & the Lizard Wizard - PetroDragonic Apocalypse; or, Dawn of Eter~c526.mp3 All seven tracks on that record reduced to the same string bar the hash. The path fitted; the result was seven files nobody could tell apart on the device, which is a worse outcome than the failure it replaced. Cut from the middle instead, giving two thirds of the remaining room to the tail because the head is generally a restatement of the directory the file already sits in: King Gizzard & the Lizard~c526~ginning of Merciless Damnation - 07 - Flamethrower.mp3 The eight real paths that prompted this are now regression tests: every track on that album keeps its number and title, all seven names stay distinct, and The Beatles' "The Long One" -- whose length is the title itself rather than a repeated album name -- keeps both ends.
This commit is contained in:
+21
-6
@@ -168,20 +168,35 @@ def fat32_safe(component):
|
||||
|
||||
|
||||
def shorten_component(component, budget):
|
||||
"""Return a component of at most `budget` characters, marked as shortened.
|
||||
"""Return a component of at most `budget` characters, cut from the middle.
|
||||
|
||||
The mark is four hex digits of the original name. Two different long names
|
||||
would otherwise cut down to the same string, and a silent collision between
|
||||
two tracks is worse than an ugly filename.
|
||||
From the middle, not the end, because of how these names are built. Lidarr
|
||||
writes "Artist - Album - 07 - Flamethrower.mp3" inside a directory already
|
||||
named for that artist and album, so the informative part -- the track
|
||||
number and title -- is at the very end. Cutting from the end discards it
|
||||
and leaves every track on the record with the same name.
|
||||
|
||||
The four hex digits are of the original component. Two names sharing both a
|
||||
head and a tail would otherwise produce the same string, and a silent
|
||||
collision between two tracks is worse than an ugly filename.
|
||||
"""
|
||||
stem, dot, extension = component.rpartition(".")
|
||||
if not dot or len(extension) > 4:
|
||||
stem, extension = component, ""
|
||||
else:
|
||||
extension = dot + extension
|
||||
|
||||
digest = hashlib.blake2s(component.encode("utf-8"), digest_size=2).hexdigest()
|
||||
tail = f"~{digest}{extension}"
|
||||
return stem[: max(1, budget - len(tail))].rstrip(". ") + tail
|
||||
marker = f"~{digest}~"
|
||||
room = max(2, budget - len(extension) - len(marker))
|
||||
if room >= len(stem):
|
||||
return stem + extension
|
||||
|
||||
# Two thirds to the tail: the head is usually a restatement of the
|
||||
# directory it sits in, and the tail is what tells two tracks apart.
|
||||
keep_end = min(len(stem), room * 2 // 3)
|
||||
keep_start = max(1, room - keep_end)
|
||||
return stem[:keep_start].rstrip(". ") + marker + stem[len(stem) - keep_end :] + extension
|
||||
|
||||
|
||||
def fit_path(relative, budget):
|
||||
|
||||
Reference in New Issue
Block a user