feat: recursively traverse directories and skip UNIX hidden ones
This commit is contained in:
parent
bdbbfff539
commit
afcc1f491e
3 changed files with 52 additions and 8 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
|
@ -161,6 +161,7 @@ dependencies = [
|
||||||
"camino",
|
"camino",
|
||||||
"clap",
|
"clap",
|
||||||
"m3u",
|
"m3u",
|
||||||
|
"once_cell",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
|
||||||
|
|
@ -10,3 +10,4 @@ anyhow = "1.0.75"
|
||||||
camino = "1.1.6"
|
camino = "1.1.6"
|
||||||
clap = { version = "4.4.0", features = ["derive"] }
|
clap = { version = "4.4.0", features = ["derive"] }
|
||||||
m3u = "1.0.0"
|
m3u = "1.0.0"
|
||||||
|
once_cell = "1.18.0"
|
||||||
|
|
|
||||||
58
src/main.rs
58
src/main.rs
|
|
@ -2,6 +2,7 @@ use anyhow::Result;
|
||||||
use camino::{Utf8Path, Utf8PathBuf};
|
use camino::{Utf8Path, Utf8PathBuf};
|
||||||
use clap::{Parser, Subcommand};
|
use clap::{Parser, Subcommand};
|
||||||
use m3u::Entry;
|
use m3u::Entry;
|
||||||
|
use once_cell::sync::Lazy;
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
|
|
||||||
/// Check if files in a playlist actually exist.
|
/// Check if files in a playlist actually exist.
|
||||||
|
|
@ -28,17 +29,57 @@ enum Mode {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_directories(base_directory: &str, is_relative: bool) -> Result<HashSet<String>> {
|
static AUDIO_EXTENSIONS: Lazy<HashSet<&str>> =
|
||||||
|
Lazy::new(|| HashSet::from(["m4a", "mp3", "ogg", "flac", "opus"]));
|
||||||
|
|
||||||
|
fn has_audio_files(path: &Utf8Path) -> Result<bool> {
|
||||||
|
let any_audio_file = path
|
||||||
|
.read_dir_utf8()?
|
||||||
|
.map(|entry| {
|
||||||
|
let entry = entry?;
|
||||||
|
if entry.metadata()?.is_file() {
|
||||||
|
if let Some(extension) = entry.path().extension() {
|
||||||
|
Ok(AUDIO_EXTENSIONS.contains(extension))
|
||||||
|
} else {
|
||||||
|
Ok(false)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Ok(false)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.any(|res: Result<bool>| res.unwrap_or(false));
|
||||||
|
Ok(any_audio_file)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_directories(
|
||||||
|
base_directory: &Utf8Path,
|
||||||
|
relative_to: Option<String>,
|
||||||
|
) -> Result<HashSet<String>> {
|
||||||
let mut result = HashSet::<String>::new();
|
let mut result = HashSet::<String>::new();
|
||||||
for entry in Utf8Path::new(base_directory).read_dir_utf8()? {
|
for entry in base_directory.read_dir_utf8()? {
|
||||||
let entry = entry?;
|
let entry = entry?;
|
||||||
if entry.metadata()?.is_dir() {
|
if entry.metadata()?.is_dir() {
|
||||||
let p = if is_relative {
|
// Skip dot directories
|
||||||
entry.file_name().to_string()
|
if entry.file_name().starts_with(".") {
|
||||||
} else {
|
continue;
|
||||||
entry.path().to_string()
|
}
|
||||||
|
let p = match &relative_to {
|
||||||
|
Some(base) => {
|
||||||
|
if base.is_empty() {
|
||||||
|
entry.file_name().to_owned()
|
||||||
|
} else {
|
||||||
|
format!("{base}/{dir}", dir = entry.file_name())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => entry.path().to_string(),
|
||||||
};
|
};
|
||||||
result.insert(p);
|
// The directory must have audio files to count
|
||||||
|
if has_audio_files(entry.path()).unwrap_or(false) {
|
||||||
|
result.insert(p.clone());
|
||||||
|
}
|
||||||
|
// Recursively check
|
||||||
|
let relative_to = relative_to.as_ref().map(|_| p);
|
||||||
|
result.extend(get_directories(entry.path(), relative_to).unwrap_or_default());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(result)
|
Ok(result)
|
||||||
|
|
@ -71,7 +112,8 @@ fn main() -> Result<()> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let actual_directories = get_directories(&base_directory, relative)?;
|
let relative_to = if relative { Some(String::new()) } else { None };
|
||||||
|
let actual_directories = get_directories(Utf8Path::new(&base_directory), relative_to)?;
|
||||||
let mut missing_directories = actual_directories
|
let mut missing_directories = actual_directories
|
||||||
.difference(&playlist_directories)
|
.difference(&playlist_directories)
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue