Skip to content

Commit 1dd0961

Browse files
committed
fix: improve canonicalization behavior
1 parent b3d9510 commit 1dd0961

3 files changed

Lines changed: 55 additions & 40 deletions

File tree

src/library/scan/discover.rs

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -157,11 +157,25 @@ const CLEANUP_PAGE_SIZE: i64 = 1000;
157157
/// large removals (e.g. an unmounted volume or a big removed folder).
158158
const CLEANUP_TX_CHUNK: usize = 500;
159159

160-
/// Canonicalize a path, falling back to the original when it can't be resolved (e.g. the
161-
/// directory was removed from disk). Stored paths in the scan record are already canonical, so if
162-
/// we have a file in the record (and it doesn't exist any more) it should still work.
160+
/// Canonicalize a path. When it can't be resolved directly (e.g. a removed folder or an unplugged
161+
/// drive), canonicalize the nearest existing ancestor and re-append the rest, so symlinked
162+
/// prefixes still resolve and the result stays comparable with stored paths, which are canonical.
163+
/// Falls back to the original path when no ancestor resolves.
163164
fn canonicalize_or_keep(path: &Utf8Path) -> Utf8PathBuf {
164-
path.canonicalize_utf8().unwrap_or_else(|_| path.to_owned())
165+
if let Ok(canonical) = path.canonicalize_utf8() {
166+
return canonical;
167+
}
168+
let mut current = path.parent();
169+
while let Some(ancestor) = current {
170+
if let Ok(canonical) = ancestor.canonicalize_utf8() {
171+
let tail = path
172+
.strip_prefix(ancestor)
173+
.expect("ancestor is a prefix of path");
174+
return canonical.join(tail);
175+
}
176+
current = ancestor.parent();
177+
}
178+
path.to_owned()
165179
}
166180

167181
/// Remove tracks that no longer belong in the library (deleted, moved, etc). Uses both the scan

src/services/controllers/windows.rs

Lines changed: 34 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -60,48 +60,47 @@ impl WindowsController {
6060
}))?;
6161

6262
let bridge = self.bridge.clone();
63-
self.controls.PlaybackPositionChangeRequested(&TypedEventHandler::<
64-
SystemMediaTransportControls,
65-
PlaybackPositionChangeRequestedEventArgs,
66-
>::new(move |_, args| {
67-
let position = args
68-
.as_ref()
69-
.unwrap()
70-
.RequestedPlaybackPosition()
71-
.unwrap();
63+
self.controls
64+
.PlaybackPositionChangeRequested(&TypedEventHandler::<
65+
SystemMediaTransportControls,
66+
PlaybackPositionChangeRequestedEventArgs,
67+
>::new(move |_, args| {
68+
let position = args.as_ref().unwrap().RequestedPlaybackPosition().unwrap();
7269

73-
// TimeSpan is measured in 100ns intervals
74-
bridge.seek(position.Duration as f64 / 10_000_000.0);
70+
// TimeSpan is measured in 100ns intervals
71+
bridge.seek(position.Duration as f64 / 10_000_000.0);
7572

76-
Ok(())
77-
}))?;
73+
Ok(())
74+
}))?;
7875

7976
let bridge = self.bridge.clone();
80-
self.controls.ShuffleEnabledChangeRequested(&TypedEventHandler::<
81-
SystemMediaTransportControls,
82-
ShuffleEnabledChangeRequestedEventArgs,
83-
>::new(move |_, _| {
84-
// TODO: do better than this
85-
bridge.toggle_shuffle();
77+
self.controls
78+
.ShuffleEnabledChangeRequested(&TypedEventHandler::<
79+
SystemMediaTransportControls,
80+
ShuffleEnabledChangeRequestedEventArgs,
81+
>::new(move |_, _| {
82+
// TODO: do better than this
83+
bridge.toggle_shuffle();
8684

87-
Ok(())
88-
}))?;
85+
Ok(())
86+
}))?;
8987

9088
let bridge = self.bridge.clone();
91-
self.controls.AutoRepeatModeChangeRequested(&TypedEventHandler::<
92-
SystemMediaTransportControls,
93-
AutoRepeatModeChangeRequestedEventArgs,
94-
>::new(move |_, args| {
95-
let mode = args.as_ref().unwrap().RequestedAutoRepeatMode().unwrap();
96-
97-
bridge.set_repeat(match mode {
98-
MediaPlaybackAutoRepeatMode::List => RepeatState::Repeating,
99-
MediaPlaybackAutoRepeatMode::Track => RepeatState::RepeatingOne,
100-
_ => RepeatState::NotRepeating,
101-
});
102-
103-
Ok(())
104-
}))?;
89+
self.controls
90+
.AutoRepeatModeChangeRequested(&TypedEventHandler::<
91+
SystemMediaTransportControls,
92+
AutoRepeatModeChangeRequestedEventArgs,
93+
>::new(move |_, args| {
94+
let mode = args.as_ref().unwrap().RequestedAutoRepeatMode().unwrap();
95+
96+
bridge.set_repeat(match mode {
97+
MediaPlaybackAutoRepeatMode::List => RepeatState::Repeating,
98+
MediaPlaybackAutoRepeatMode::Track => RepeatState::RepeatingOne,
99+
_ => RepeatState::NotRepeating,
100+
});
101+
102+
Ok(())
103+
}))?;
105104

106105
Ok(())
107106
}

src/settings/scan.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,9 @@ fn retrieve_default_paths() -> Vec<Utf8PathBuf> {
4848
let folders = match folders {
4949
Ok(folders) => folders,
5050
Err(e) => {
51-
warn!("Couldn't retrieve the Music library ({e}): nothing will be scanned by default.");
51+
warn!(
52+
"Couldn't retrieve the Music library ({e}): nothing will be scanned by default."
53+
);
5254
return vec![];
5355
}
5456
};

0 commit comments

Comments
 (0)