use super::release::Asset;
use crate::infra::client::Client;
use crate::model::asset_name::AssetName;
use crate::model::release::AssetError;
use std::fmt::{Display, Formatter};
#[derive(Debug, PartialEq, Eq)]
pub enum Tool {
Known(ToolInfo),
Error(ToolError),
}
#[derive(Debug, PartialEq, Eq)]
pub enum ToolError {
Suggestion { perhaps: String },
Invalid,
}
impl Display for ToolError {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
ToolError::Suggestion { perhaps } => {
write!(f, "[suggestion] Perhaps you meant: '{}'?", perhaps)
}
ToolError::Invalid => write!(f, "[error] Not detailed enough configuration"),
}
}
}
#[derive(Debug, PartialEq, Eq)]
pub enum ToolInfoTag {
Latest,
Specific(String),
}
const LATEST_VERSION: &str = "latest";
impl ToolInfoTag {
pub fn to_str_version(&self) -> String {
match self {
Self::Latest => LATEST_VERSION.to_owned(),
Self::Specific(version) => format!("tags/{}", version),
}
}
}
#[derive(Debug, PartialEq, Eq)]
pub struct ToolInfo {
pub owner: String,
pub repo: String,
pub exe_name: String,
pub tag: ToolInfoTag,
pub asset_name: AssetName,
}
impl ToolInfo {
pub fn select_asset(&self, assets: &[Asset]) -> Result<Asset, AssetError> {
match self.asset_name.get_name_by_os() {
None => Err(AssetError::OsSelectorUnknown),
Some(asset_name) => {
let mut filtered_assets = assets
.iter()
.filter(|&asset| asset.name.contains(asset_name))
.map(|asset| asset.to_owned())
.collect::<Vec<Asset>>();
match filtered_assets.len() {
0 => Err(AssetError::NotFound(asset_name.clone())),
1 => Ok(filtered_assets.remove(0)),
_ => {
let assets: Vec<String> =
filtered_assets.into_iter().map(|item| item.name).collect();
Err(AssetError::MultipleFound(assets))
}
}
}
}
}
}
pub struct ToolAsset {
pub tool_name: String,
pub tag: String,
pub exe_name: String,
pub asset: Asset,
pub client: Client,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn asset_found() {
let asset_name = "asset";
let tool_info = ToolInfo {
owner: "owner".to_string(),
repo: "repo".to_string(),
exe_name: "exe".to_string(),
tag: ToolInfoTag::Latest,
asset_name: AssetName {
linux: Some(asset_name.to_string()),
macos: Some(asset_name.to_string()),
windows: Some(asset_name.to_string()),
},
};
let assets = vec![
Asset {
id: 1,
name: "1".to_string(),
size: 10,
},
Asset {
id: 2,
name: asset_name.to_string(),
size: 50,
},
Asset {
id: 3,
name: "3".to_string(),
size: 77,
},
];
assert_eq!(
tool_info.select_asset(&assets),
Ok(Asset {
id: 2,
name: asset_name.to_string(),
size: 50
})
);
}
#[test]
fn multiple_asset_found() {
let asset_name = "asset";
let tool_info = ToolInfo {
owner: "owner".to_string(),
repo: "repo".to_string(),
exe_name: "exe".to_string(),
tag: ToolInfoTag::Latest,
asset_name: AssetName {
linux: Some(asset_name.to_string()),
macos: Some(asset_name.to_string()),
windows: Some(asset_name.to_string()),
},
};
let assets = vec![
Asset {
id: 1,
name: "asset_1".to_string(),
size: 10,
},
Asset {
id: 2,
name: "asset_2".to_string(),
size: 50,
},
Asset {
id: 3,
name: "asset_3".to_string(),
size: 77,
},
Asset {
id: 3,
name: "not a match".to_string(),
size: 77,
},
];
assert_eq!(
tool_info.select_asset(&assets),
Err(AssetError::MultipleFound(vec![
"asset_1".into(),
"asset_2".into(),
"asset_3".into()
]))
);
}
#[test]
fn asset_not_found() {
let asset_name = "asset";
let tool_info = ToolInfo {
owner: "owner".to_string(),
repo: "repo".to_string(),
exe_name: "exe".to_string(),
tag: ToolInfoTag::Latest,
asset_name: AssetName {
linux: Some(asset_name.to_string()),
macos: Some(asset_name.to_string()),
windows: Some(asset_name.to_string()),
},
};
let assets = vec![
Asset {
id: 1,
name: "1".to_string(),
size: 10,
},
Asset {
id: 2,
name: "2".to_string(),
size: 50,
},
Asset {
id: 3,
name: "3".to_string(),
size: 77,
},
];
assert_eq!(
tool_info.select_asset(&assets),
Err(AssetError::NotFound(asset_name.to_string()))
);
}
#[test]
fn asset_os_selector_unknown() {
let tool_info = ToolInfo {
owner: "owner".to_string(),
repo: "repo".to_string(),
exe_name: "exe".to_string(),
tag: ToolInfoTag::Latest,
asset_name: AssetName {
linux: None,
macos: None,
windows: None,
},
};
assert_eq!(
tool_info.select_asset(&[]),
Err(AssetError::OsSelectorUnknown)
);
}
}