Skip to content

Commit

Permalink
refactor(cable): always create default cable channels in user directo…
Browse files Browse the repository at this point in the history
…ry if no cable channels exist (#213)

Fixes #212
  • Loading branch information
alexpasmantier authored Jan 4, 2025
1 parent 971a2e7 commit 657af5e
Showing 1 changed file with 41 additions and 21 deletions.
62 changes: 41 additions & 21 deletions crates/television/cable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ const DEFAULT_CABLE_CHANNELS: &str =
const DEFAULT_CABLE_CHANNELS: &str =
include_str!("../../cable/windows-channels.toml");

const DEFAULT_CABLE_CHANNELS_FILE_NAME: &str = "default_channels.toml";

/// Load the cable configuration from the config directory.
///
/// Cable is loaded by compiling all files that match the following
Expand All @@ -45,16 +47,7 @@ pub fn load_cable_channels() -> Result<CableChannels> {
// filter the files that match the pattern
let file_paths = files
.filter_map(|f| f.ok().map(|f| f.path()))
.filter(|p| {
p.extension()
.and_then(|e| e.to_str())
.map_or(false, |e| e.to_lowercase() == CABLE_FILE_FORMAT)
})
.filter(|p| {
p.file_stem()
.and_then(|s| s.to_str())
.map_or(false, |s| s.ends_with(CABLE_FILE_NAME_SUFFIX))
});
.filter(|p| is_cable_file_format(p) && p.is_file());

let user_defined_prototypes = file_paths.fold(Vec::new(), |mut acc, p| {
let r: ChannelPrototypes = toml::from_str(
Expand All @@ -66,21 +59,48 @@ pub fn load_cable_channels() -> Result<CableChannels> {
acc
});

debug!("Loaded cable channels: {:?}", user_defined_prototypes);
// If no user defined prototypes are found, write the default prototypes for the current
// platform to the config directory
if user_defined_prototypes.is_empty() {
debug!("No user defined cable channels found");
// write the default cable channels to the config directory
let default_channels_path =
config_dir.join(DEFAULT_CABLE_CHANNELS_FILE_NAME);
std::fs::write(default_channels_path, DEFAULT_CABLE_CHANNELS)?;
}

let default_prototypes: ChannelPrototypes =
toml::from_str(DEFAULT_CABLE_CHANNELS)
.expect("Unable to parse default cable channels");
debug!("Loaded cable channels: {:?}", user_defined_prototypes);

let mut cable_channels = HashMap::new();
// chaining default with user defined prototypes so that users may override the
// default prototypes
for prototype in default_prototypes
.prototypes
.into_iter()
.chain(user_defined_prototypes)
{
for prototype in user_defined_prototypes {
cable_channels.insert(prototype.name.clone(), prototype);
}
Ok(CableChannels(cable_channels))
}

fn is_cable_file_format<P>(p: P) -> bool
where
P: AsRef<std::path::Path>,
{
let p = p.as_ref();
p.file_stem()
.and_then(|s| s.to_str())
.map_or(false, |s| s.ends_with(CABLE_FILE_NAME_SUFFIX))
&& p.extension()
.and_then(|e| e.to_str())
.map_or(false, |e| e.to_lowercase() == CABLE_FILE_FORMAT)
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_is_cable_file() {
let path = std::path::Path::new("cable_channels.toml");
assert!(is_cable_file_format(path));

let path = std::path::Path::new(DEFAULT_CABLE_CHANNELS_FILE_NAME);
assert!(is_cable_file_format(path));
}
}

0 comments on commit 657af5e

Please sign in to comment.