From 704ab512bf30eeea2bf50ae469290d4f73e9820c Mon Sep 17 00:00:00 2001 From: euzu Date: Fri, 13 Jun 2025 08:42:47 +0200 Subject: [PATCH] clippy fixes --- src/foundation/mapper.rs | 10 ++-- src/processing/parser/xmltv.rs | 10 +--- src/repository/bplustree.rs | 5 +- src/repository/kodi_repository.rs | 92 ++++++++++++++--------------- src/repository/user_repository.rs | 8 +-- src/repository/xtream_repository.rs | 8 +-- src/tools/directed_graph.rs | 12 ++-- 7 files changed, 70 insertions(+), 75 deletions(-) diff --git a/src/foundation/mapper.rs b/src/foundation/mapper.rs index 3bbbb43a1..a5a32cd31 100644 --- a/src/foundation/mapper.rs +++ b/src/foundation/mapper.rs @@ -1212,7 +1212,7 @@ mod tests { @Group = "United States - Entertainment" "#; - let mapper = MapperScript::parse(dsl).expect("Parsing failed"); + let mapper = MapperScript::parse(dsl, None).expect("Parsing failed"); println!("Program: {mapper:?}"); let mut channels: Vec = vec![ ("D", "HD"), ("A", "FHD"), ("Z", ""), ("K", "HD"), ("B", "HD"), ("A", "HD"), @@ -1223,7 +1223,7 @@ mod tests { let mut accessor = ValueAccessor { pli, }; - mapper.eval(&mut accessor); + mapper.eval(&mut accessor, None); println!("Result: {pli:?}"); } @@ -1241,7 +1241,7 @@ mod tests { #[test] fn test_complex() { - let script = r##" + let script = r#" print("LOCAL") coast = @Caption ~ "!COAST!" quality = uppercase(@Caption ~ "!QUALITY!") @@ -1297,8 +1297,8 @@ mod tests { @Group = concat("🇺🇸 > USA - ", network, " Locals") } } - "##; - let mapper = MapperScript::parse(script).expect("Parsing failed"); + "#; + let mapper = MapperScript::parse(script, None).expect("Parsing failed"); println!("Program: {mapper:?}"); } } diff --git a/src/processing/parser/xmltv.rs b/src/processing/parser/xmltv.rs index 913013890..47419f9b8 100644 --- a/src/processing/parser/xmltv.rs +++ b/src/processing/parser/xmltv.rs @@ -533,10 +533,8 @@ mod tests { /// // This will assert that various channel names are normalized as expected. /// ``` fn normalize() { - let mut epg_smart_cfg = EpgSmartMatchConfig::default(); - epg_smart_cfg.enabled = true; - epg_smart_cfg.name_prefix = EpgNamePrefix::Suffix(".".to_string()); - let _ = epg_smart_cfg.prepare(); + let mut epg_smart_cfg = EpgSmartMatchConfig { enabled: true, name_prefix: EpgNamePrefix::Suffix(".".to_string()), ..Default::default() }; + let _ = epg_smart_cfg.prepare(); println!("{epg_smart_cfg:?}"); assert_eq!("supersport6.ru", normalize_channel_name("RU: SUPERSPORT 6 ᴿᴬᵂ", &epg_smart_cfg)); assert_eq!("odisea.sat", normalize_channel_name("SAT: ODISEA ᴿᴬᵂ", &epg_smart_cfg)); @@ -562,9 +560,7 @@ mod tests { /// ``` fn test_metaphone() { let metaphone = Metaphone::default(); - let mut epg_smart_cfg = EpgSmartMatchConfig::default(); - epg_smart_cfg.enabled = true; - epg_smart_cfg.name_prefix = EpgNamePrefix::Suffix(".".to_string()); + let mut epg_smart_cfg = EpgSmartMatchConfig { enabled: true, name_prefix: EpgNamePrefix::Suffix(".".to_string()), ..Default::default() }; let _ = epg_smart_cfg.prepare(); println!("{epg_smart_cfg:?}"); // assert_eq!("supersport6.ru", metaphone.encode(&normalize_channel_name("RU: SUPERSPORT 6 ᴿᴬᵂ", &epg_normalize_cfg))); diff --git a/src/repository/bplustree.rs b/src/repository/bplustree.rs index c757d23fe..e52fed0d7 100644 --- a/src/repository/bplustree.rs +++ b/src/repository/bplustree.rs @@ -835,7 +835,7 @@ mod tests { }; tree_update.update(&i, new_record)?; } else { - assert!(false, "{content} {i} not found"); + panic!("{content} {i} not found"); } } @@ -857,7 +857,7 @@ mod tests { #[test] - fn insert_dulplicate_test() -> io::Result<()> { + fn insert_dulplicate_test() { let content = "Entry"; let mut tree = BPlusTree::::new(); for i in 0u32..=500 { @@ -879,7 +879,6 @@ mod tests { }); }); - Ok(()) } #[test] diff --git a/src/repository/kodi_repository.rs b/src/repository/kodi_repository.rs index f2a80e462..b2b5a3ae7 100644 --- a/src/repository/kodi_repository.rs +++ b/src/repository/kodi_repository.rs @@ -81,7 +81,7 @@ fn extract_match(name: &str, pattern: &Regex) -> (String, Option) { ) } -//// Extracts a number from a pattern (e.g., "S01" -> 1), falling back to a default value. +/// Extracts a number from a pattern (e.g., "S01" -> 1), falling back to a default value. fn extract_season_or_episode_match_with_default( name: &str, pattern: &Regex, @@ -412,7 +412,7 @@ struct StrmFile { strm_info: StrmItemInfo, } -/// Formats names according to the official Kodi documentation, with TMDb ID for better matching. +/// Formats names according to the official Kodi documentation, with `TMDb` ID for better matching. /// Movie: /Movie Name (Year) {tmdb=XXXXX}/Movie Name (Year).strm /// Series: /Show Name (Year) {tmdb=XXXXX}/Season 01/Show Name S01E01.strm fn format_for_kodi( @@ -426,17 +426,17 @@ fn format_for_kodi( match strm_item_info.item_type { PlaylistItemType::Video => { - let id_string = if tmdb_id > 0 { format!("{}{{tmdb={}}}", separator, tmdb_id) } else { String::new() }; + let id_string = if tmdb_id > 0 { format!("{separator}{{tmdb={tmdb_id}}}") } else { String::new() }; let (name, year) = style_rename_year(&strm_item_info.title, &CONSTANTS.export_style_config, strm_item_info.release_date.as_ref()); let sanitized_title = sanitize_for_filename(name.trim(), false); - let year_string = year.map_or(String::new(), |y| format!("{}({})", separator, y)); + let year_string = year.map_or(String::new(), |y| format!("{separator}({y})")); - let base_name = format!("{}{}", sanitized_title, year_string); - let folder_name = format!("{}{}", base_name, id_string); + let base_name = format!("{sanitized_title}{year_string}"); + let folder_name = format!("{base_name}{id_string}"); let final_filename = base_name; // Kodi is flexible, filename without ID is clean. The folder has the ID. if flat { - dir_path.push(format!("{}{separator}[{}]", folder_name, category)); + dir_path.push(format!("{folder_name}{separator}[{category}]")); } else { dir_path.push(category); dir_path.push(folder_name); @@ -444,24 +444,24 @@ fn format_for_kodi( (dir_path, final_filename) } PlaylistItemType::Series => { - let id_string = if tmdb_id > 0 { format!("{}{{tmdb={}}}", separator, tmdb_id) } else { String::new() }; + let id_string = if tmdb_id > 0 { format!("{separator}{{tmdb={tmdb_id}}}") } else { String::new() }; let series_name_raw = strm_item_info.series_name.as_ref().unwrap_or(&strm_item_info.title); let (name, year) = style_rename_year(series_name_raw, &CONSTANTS.export_style_config, strm_item_info.release_date.as_ref()); let sanitized_series_name = sanitize_for_filename(name.trim(), false); - let year_string = year.map_or(String::new(), |y| format!("{}({})", separator, y)); + let year_string = year.map_or(String::new(), |y| format!("{separator}({y})")); - let series_folder_name = format!("{}{}{}", sanitized_series_name, year_string, id_string); + let series_folder_name = format!("{sanitized_series_name}{year_string}{id_string}"); let (_, season) = style_rename_season(&strm_item_info.title, &CONSTANTS.export_style_config, strm_item_info.season.as_ref()); let (_, episode) = style_rename_episode(&strm_item_info.title, &CONSTANTS.export_style_config, strm_item_info.episode.as_ref()); let season_num = season.unwrap_or(1); let episode_num = episode.unwrap_or(1); - let final_filename = format!("{}{separator}S{:02}E{:02}", sanitized_series_name, season_num, episode_num); - let season_folder = format!("Season{}{:02}", separator, season_num); + let final_filename = format!("{sanitized_series_name}{separator}S{season_num:02}E{episode_num:02}"); + let season_folder = format!("Season{separator}{season_num:02}"); if flat { - dir_path.push(format!("{}{separator}[{}]", series_folder_name, category)); + dir_path.push(format!("{series_folder_name}{separator}[{category}]")); dir_path.push(season_folder); } else { dir_path.push(category); @@ -488,17 +488,17 @@ fn format_for_plex( match strm_item_info.item_type { PlaylistItemType::Video => { - let id_string = if tmdb_id > 0 { format!("{}{{tmdb-{}}}", separator, tmdb_id) } else { String::new() }; + let id_string = if tmdb_id > 0 { format!("{separator}{{tmdb-{tmdb_id}}}") } else { String::new() }; let (name, year) = style_rename_year(&strm_item_info.title, &CONSTANTS.export_style_config, strm_item_info.release_date.as_ref()); let sanitized_title = sanitize_for_filename(name.trim(), false); - let year_string = year.map_or(String::new(), |y| format!("{}({})", separator, y)); + let year_string = year.map_or(String::new(), |y| format!("{separator}({y})")); - let base_name = format!("{}{}", sanitized_title, year_string); - let folder_name = format!("{}{}", base_name, id_string); + let base_name = format!("{sanitized_title}{year_string}"); + let folder_name = format!("{base_name}{id_string}"); let final_filename = base_name; // Plex: ID is only in the folder name. if flat { - dir_path.push(format!("{}{separator}[{}]", folder_name, category)); + dir_path.push(format!("{folder_name}{separator}[{category}]")); } else { dir_path.push(category); dir_path.push(folder_name); @@ -506,13 +506,13 @@ fn format_for_plex( (dir_path, final_filename) } PlaylistItemType::Series => { - let id_string = if tmdb_id > 0 { format!("{}{{tmdb-{}}}", separator, tmdb_id) } else { String::new() }; + let id_string = if tmdb_id > 0 { format!("{separator}{{tmdb-{tmdb_id}}}") } else { String::new() }; let series_name_raw = strm_item_info.series_name.as_ref().unwrap_or(&strm_item_info.title); let (name, year) = style_rename_year(series_name_raw, &CONSTANTS.export_style_config, strm_item_info.release_date.as_ref()); let sanitized_series_name = sanitize_for_filename(name.trim(), false); - let year_string = year.map_or(String::new(), |y| format!("{}({})", separator, y)); + let year_string = year.map_or(String::new(), |y| format!("{separator}({y})")); - let series_folder_name = format!("{}{}{}", sanitized_series_name, year_string, id_string); + let series_folder_name = format!("{sanitized_series_name}{year_string}{id_string}"); let (_, season) = style_rename_season(&strm_item_info.title, &CONSTANTS.export_style_config, strm_item_info.season.as_ref()); let (_, episode) = style_rename_episode(&strm_item_info.title, &CONSTANTS.export_style_config, strm_item_info.episode.as_ref()); @@ -520,11 +520,11 @@ fn format_for_plex( let episode_num = episode.unwrap_or(1); // Plex standard: lowercase 's' and hyphens as separators. - let final_filename = format!("{} - s{:02}e{:02}", sanitized_series_name, season_num, episode_num); - let season_folder = format!("Season{}{:02}", separator, season_num); + let final_filename = format!("{sanitized_series_name} - s{season_num:02}e{episode_num:02}"); + let season_folder = format!("Season{separator}{season_num:02}"); if flat { - dir_path.push(format!("{}{separator}[{}]", series_folder_name, category)); + dir_path.push(format!("{series_folder_name}{separator}[{category}]")); dir_path.push(season_folder); } else { dir_path.push(category); @@ -552,17 +552,17 @@ fn format_for_emby( match strm_item_info.item_type { PlaylistItemType::Video => { // Emby prefers the ID in the filename. - let id_string = if tmdb_id > 0 { format!("{} [tmdbid={}]", separator, tmdb_id) } else { String::new() }; + let id_string = if tmdb_id > 0 { format!("{separator} [tmdbid={tmdb_id}]") } else { String::new() }; let (name, year) = style_rename_year(&strm_item_info.title, &CONSTANTS.export_style_config, strm_item_info.release_date.as_ref()); let sanitized_title = sanitize_for_filename(name.trim(), false); - let year_string = year.map_or(String::new(), |y| format!("{}({})", separator, y)); + let year_string = year.map_or(String::new(), |y| format!("{separator}({y})")); - let base_name = format!("{}{}", sanitized_title, year_string); + let base_name = format!("{sanitized_title}{year_string}"); let folder_name = base_name.clone(); // Folder name does not contain the ID. - let final_filename = format!("{}{}", base_name, id_string); + let final_filename = format!("{base_name}{id_string}"); if flat { - dir_path.push(format!("{}{separator}[{}]", folder_name, category)); + dir_path.push(format!("{folder_name}{separator}[{category}]")); } else { dir_path.push(category); dir_path.push(folder_name); @@ -571,13 +571,13 @@ fn format_for_emby( } PlaylistItemType::Series => { // For series, the ID goes in the folder name. - let id_string = if tmdb_id > 0 { format!("{} [tmdbid={}]", separator, tmdb_id) } else { String::new() }; + let id_string = if tmdb_id > 0 { format!("{separator} [tmdbid={tmdb_id}]") } else { String::new() }; let series_name_raw = strm_item_info.series_name.as_ref().unwrap_or(&strm_item_info.title); let (name, year) = style_rename_year(series_name_raw, &CONSTANTS.export_style_config, strm_item_info.release_date.as_ref()); let sanitized_series_name = sanitize_for_filename(name.trim(), false); - let year_string = year.map_or(String::new(), |y| format!("{}({})", separator, y)); + let year_string = year.map_or(String::new(), |y| format!("{separator}({y})")); - let series_folder_name = format!("{}{}{}", sanitized_series_name, year_string, id_string); + let series_folder_name = format!("{sanitized_series_name}{year_string}{id_string}"); let (_, season) = style_rename_season(&strm_item_info.title, &CONSTANTS.export_style_config, strm_item_info.season.as_ref()); let (_, episode) = style_rename_episode(&strm_item_info.title, &CONSTANTS.export_style_config, strm_item_info.episode.as_ref()); @@ -585,11 +585,11 @@ fn format_for_emby( let episode_num = episode.unwrap_or(1); // Emby/Jellyfin standard: uppercase 'S' and hyphens. - let final_filename = format!("{} - S{:02}E{:02}", sanitized_series_name, season_num, episode_num); - let season_folder = format!("Season{}{:02}", separator, season_num); + let final_filename = format!("{sanitized_series_name} - S{season_num:02}E{episode_num:02}"); + let season_folder = format!("Season{separator}{season_num:02}"); if flat { - dir_path.push(format!("{}{separator}[{}]", series_folder_name, category)); + dir_path.push(format!("{series_folder_name}{separator}[{category}]")); dir_path.push(season_folder); } else { dir_path.push(category); @@ -616,17 +616,17 @@ fn format_for_jellyfin( match strm_item_info.item_type { PlaylistItemType::Video => { - let id_string = if tmdb_id > 0 { format!("{} [tmdbid-{}]", separator, tmdb_id) } else { String::new() }; + let id_string = if tmdb_id > 0 { format!("{separator} [tmdbid-{tmdb_id}]") } else { String::new() }; let (name, year) = style_rename_year(&strm_item_info.title, &CONSTANTS.export_style_config, strm_item_info.release_date.as_ref()); let sanitized_title = sanitize_for_filename(name.trim(), false); - let year_string = year.map_or(String::new(), |y| format!("{}({})", separator, y)); + let year_string = year.map_or(String::new(), |y| format!("{separator}({y})")); - let base_name = format!("{}{}", sanitized_title, year_string); - let folder_name = format!("{}{}", base_name, id_string); + let base_name = format!("{sanitized_title}{year_string}"); + let folder_name = format!("{base_name}{id_string}"); let final_filename = base_name; // Jellyfin: ID is only in the folder name. if flat { - dir_path.push(format!("{}{separator}[{}]", folder_name, category)); + dir_path.push(format!("{folder_name}{separator}[{category}]")); } else { dir_path.push(category); dir_path.push(folder_name); @@ -634,13 +634,13 @@ fn format_for_jellyfin( (dir_path, final_filename) } PlaylistItemType::Series => { - let id_string = if tmdb_id > 0 { format!("{} [tmdbid-{}]", separator, tmdb_id) } else { String::new() }; + let id_string = if tmdb_id > 0 { format!("{separator} [tmdbid-{tmdb_id}]") } else { String::new() }; let series_name_raw = strm_item_info.series_name.as_ref().unwrap_or(&strm_item_info.title); let (name, year) = style_rename_year(series_name_raw, &CONSTANTS.export_style_config, strm_item_info.release_date.as_ref()); let sanitized_series_name = sanitize_for_filename(name.trim(), false); - let year_string = year.map_or(String::new(), |y| format!("{}({})", separator, y)); + let year_string = year.map_or(String::new(), |y| format!("{separator}({y})")); - let series_folder_name = format!("{}{}{}", sanitized_series_name, year_string, id_string); + let series_folder_name = format!("{sanitized_series_name}{year_string}{id_string}"); let (_, season) = style_rename_season(&strm_item_info.title, &CONSTANTS.export_style_config, strm_item_info.season.as_ref()); let (_, episode) = style_rename_episode(&strm_item_info.title, &CONSTANTS.export_style_config, strm_item_info.episode.as_ref()); @@ -648,11 +648,11 @@ fn format_for_jellyfin( let episode_num = episode.unwrap_or(1); // Emby/Jellyfin standard: uppercase 'S' and hyphens. - let final_filename = format!("{} - S{:02}E{:02}", sanitized_series_name, season_num, episode_num); - let season_folder = format!("Season{}{:02}", separator, season_num); + let final_filename = format!("{sanitized_series_name} - S{season_num:02}E{episode_num:02}"); + let season_folder = format!("Season{separator}{season_num:02}"); if flat { - dir_path.push(format!("{}{separator}[{}]", series_folder_name, category)); + dir_path.push(format!("{series_folder_name}{separator}[{category}]")); dir_path.push(season_folder); } else { dir_path.push(category); diff --git a/src/repository/user_repository.rs b/src/repository/user_repository.rs index db18bd930..edddbb5cc 100644 --- a/src/repository/user_repository.rs +++ b/src/repository/user_repository.rs @@ -415,7 +415,7 @@ mod tests { server: Some("default".to_string()), epg_timeshift: None, created_at: None, - exp_date: Some(1672705545), + exp_date: Some(1_672_705_545), max_connections: 1, status: Some(ProxyUserStatus::Active), ui_enabled: true, @@ -429,7 +429,7 @@ mod tests { server: Some("default".to_string()), epg_timeshift: None, created_at: None, - exp_date: Some(1672705545), + exp_date: Some(1_672_705_545), max_connections: 1, status: Some(ProxyUserStatus::Expired), ui_enabled: true, @@ -443,7 +443,7 @@ mod tests { server: Some("default".to_string()), epg_timeshift: None, created_at: None, - exp_date: Some(1672705545), + exp_date: Some(1_672_705_545), max_connections: 1, status: Some(ProxyUserStatus::Expired), ui_enabled: true, @@ -457,7 +457,7 @@ mod tests { server: Some("default".to_string()), epg_timeshift: None, created_at: None, - exp_date: Some(1672705545), + exp_date: Some(1_672_705_545), max_connections: 1, status: Some(ProxyUserStatus::Expired), ui_enabled: true, diff --git a/src/repository/xtream_repository.rs b/src/repository/xtream_repository.rs index 3e8893d28..c2e7d1d86 100644 --- a/src/repository/xtream_repository.rs +++ b/src/repository/xtream_repository.rs @@ -795,13 +795,13 @@ pub async fn xtream_update_input_vod_record_from_wal_file( let provider_id = u32::from_le_bytes(provider_id_bytes); if reader.read_exact(&mut tmdb_id_bytes).is_err() { - error!("Unexpected EOF after reading provider_id {} for VOD record.", provider_id); + error!("Unexpected EOF after reading provider_id {provider_id} for VOD record."); break; } let tmdb_id = u32::from_le_bytes(tmdb_id_bytes); if reader.read_exact(&mut ts_bytes).is_err() { - error!("Unexpected EOF after reading tmdb_id for VOD record with provider_id {}.", provider_id); + error!("Unexpected EOF after reading tmdb_id for VOD record with provider_id {provider_id}."); break; } let ts = u64::from_le_bytes(ts_bytes); @@ -809,7 +809,7 @@ pub async fn xtream_update_input_vod_record_from_wal_file( // Read the date string length as a 4-byte u32. let mut len_bytes = [0u8; 4]; if reader.read_exact(&mut len_bytes).is_err() { - error!("Unexpected EOF when reading release_date length for VOD record with provider_id {}.", provider_id); + error!("Unexpected EOF when reading release_date length for VOD record with provider_id {provider_id}."); break; } let len = u32::from_le_bytes(len_bytes) as usize; @@ -817,7 +817,7 @@ pub async fn xtream_update_input_vod_record_from_wal_file( let release_date = if len > 0 { let mut date_buffer = vec![0u8; len]; if reader.read_exact(&mut date_buffer).is_err() { - error!("Unexpected EOF when reading release_date string for VOD record with provider_id {}.", provider_id); + error!("Unexpected EOF when reading release_date string for VOD record with provider_id {provider_id}."); break; } String::from_utf8(date_buffer).ok() diff --git a/src/tools/directed_graph.rs b/src/tools/directed_graph.rs index f264c7a78..92312ee35 100644 --- a/src/tools/directed_graph.rs +++ b/src/tools/directed_graph.rs @@ -210,7 +210,7 @@ mod tests { use crate::tools::directed_graph::DirectedGraph; use std::collections::HashSet; - fn are_vecs_equal(vec1: &Vec<&str>, vec2: Vec<&str>) -> bool { + fn are_vecs_equal(vec1: &Vec<&str>, vec2: &Vec<&str>) -> bool { let set1: HashSet = vec1.iter().map(|s| (*s).to_string()).collect(); let set2: HashSet = vec2.iter().map(|s| (*s).to_string()).collect(); @@ -263,13 +263,13 @@ mod tests { let dependencies = dependencies_opt.unwrap(); let a_deps = dependencies.get("A"); assert!(a_deps.is_some(), "No dependencies for A found"); - assert!(are_vecs_equal(a_deps.unwrap(), vec!["B"]), "Dependencies for A not match"); + assert!(are_vecs_equal(a_deps.unwrap(), &vec!["B"]), "Dependencies for A not match"); let b_deps = dependencies.get("B"); assert!(b_deps.is_some(), "No dependencies for B found"); - assert!(are_vecs_equal(b_deps.unwrap(), vec!["C", "D"]), "Dependencies for B not match"); + assert!(are_vecs_equal(b_deps.unwrap(), &vec!["C", "D"]), "Dependencies for B not match"); let c_deps = dependencies.get("C"); assert!(c_deps.is_some(), "No dependencies for C found"); - assert!(are_vecs_equal(c_deps.unwrap(), vec!["D"]), "Dependencies for C not match"); + assert!(are_vecs_equal(c_deps.unwrap(), &vec!["D"]), "Dependencies for C not match"); let d_deps = dependencies.get("D"); assert!(d_deps.is_none(), "No dependencies for D found"); } @@ -302,7 +302,7 @@ mod tests { let sorted = graph.topological_sort(); assert!(sorted.is_some(), "Could not sort"); let sorted_list = sorted.unwrap(); - assert!(are_vecs_equal(&sorted_list, vec!["D", "A", "C", "B"]), "sort order wrong"); + assert!(are_vecs_equal(&sorted_list, &vec!["D", "A", "C", "B"]), "sort order wrong"); } #[test] @@ -327,7 +327,7 @@ mod tests { let sorted = graph.topological_sort(); assert!(sorted.is_some(), "Could not sort"); let sorted_list = sorted.unwrap(); - assert!(are_vecs_equal(&sorted_list, vec!["F", "B", "A", "C", "E", "D", "G"]), "sort order wrong"); + assert!(are_vecs_equal(&sorted_list, &vec!["F", "B", "A", "C", "E", "D", "G"]), "sort order wrong"); // should be {"D": ["C", "E"], "G": ["C", "F"], "C": ["A", "B"]} assert!(graph.get_dependencies().is_some(), "No dependencies");