From 4f0cd0423ab923ea77b89e4aa666dd36f696e35f Mon Sep 17 00:00:00 2001 From: Thomas Eppers Date: Mon, 13 Sep 2021 17:05:06 +0200 Subject: [PATCH] use more functions from repo --- src/repo.rs | 60 ++++++++++++++++++++++++++++++++++++++++++++++++----- src/tags.rs | 48 ++++++++++++++++-------------------------- src/ui.rs | 8 +++---- 3 files changed, 77 insertions(+), 39 deletions(-) diff --git a/src/repo.rs b/src/repo.rs index d14d308..4bd8cc9 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -1,3 +1,7 @@ +use std::fmt; + +use regex::Regex; + use crate::common; #[derive(Debug, PartialEq)] @@ -9,6 +13,18 @@ pub enum Error { MisformedInput, } +impl fmt::Display for Error { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Error::Conversion => write!(f, "Conversion error"), + Error::Empty => write!(f, "Input is empty"), + Error::NoTagFound => write!(f, "Expected a tag"), + Error::InvalidChar => write!(f, "Invalid character found"), + Error::MisformedInput => write!(f, "Unexpected input"), + } + } +} + #[derive(Debug, PartialEq)] pub enum Repo { WithServer(String, String, String), @@ -19,7 +35,7 @@ pub enum Repo { /// check if yaml line matches and returns the split of repo string and rest pub fn match_yaml_image(input: &str) -> Option<(&str, &str)> { lazy_static::lazy_static! { - static ref REGEX: regex::Regex = regex::Regex::new(r"^( +image *: *)([a-z0-9\./:]+)").unwrap(); + static ref REGEX: Regex = Regex::new(r"^( +image *: *)([a-z0-9\./:]+)").unwrap(); } let caps = match REGEX.captures(input) { Some(caps) => caps, @@ -29,6 +45,28 @@ pub fn match_yaml_image(input: &str) -> Option<(&str, &str)> { Some((caps.get(1).unwrap().as_str(), caps.get(2).unwrap().as_str())) } +pub fn split_tag_from_repo(input: &str) -> Result<(&str, &str), Error> { + lazy_static::lazy_static! { + static ref REGEX: Regex = Regex::new(r"^([a-z0-9\./[^:]]*):?([a-z0-9._\-]*)").unwrap(); + } + let (front, back) = match REGEX.captures(input) { + None => return Err(Error::MisformedInput), + Some(caps) => { + let front = match caps.get(1) { + None => return Err(Error::MisformedInput), + Some(cap) => cap.as_str(), + }; + let back = match caps.get(2) { + None => "", + Some(cap) => cap.as_str(), + }; + (front, back) + } + }; + + Ok((front, back)) +} + pub fn split_repo(repo: &str) -> Result { let split_tag: Vec<&str> = repo.split(":").collect(); if split_tag.len() == 2 && split_tag[0].len() != 0 && split_tag[1].len() != 0 { @@ -37,8 +75,8 @@ pub fn split_repo(repo: &str) -> Result { Ok(Repo::Project("".into())) } -pub fn split_repo_without_tag(mut repo: &str) -> Result { - repo.trim(); +pub fn split_repo_without_tag(repo: &str) -> Result { + let repo = repo.trim(); let split_repo: Vec<&str> = repo.split("/").collect(); match split_repo.len() { 1 => { @@ -79,8 +117,6 @@ pub fn split_tag(repo: &str) -> Result<(&str, &str), Error> { } } -// fn - pub fn extract(repo: &str) -> Result<(Option<&str>, Option<&str>, &str), Error> { if repo.len() == 0 { return Err(Error::Empty); @@ -172,4 +208,18 @@ mod tests { Some((" image: ", "nginx")) ); } + + #[test] + fn test_split_tag_from_repo() { + use crate::repo::split_tag_from_repo as test_fn; + assert_eq!(test_fn("nginx"), Ok(("nginx", ""))); + assert_eq!(test_fn("library/nginx"), Ok(("library/nginx", ""))); + assert_eq!( + test_fn("ghcr.io/library/nginx"), + Ok(("ghcr.io/library/nginx", "")) + ); + assert_eq!(test_fn("nginx:"), Ok(("nginx", ""))); + assert_eq!(test_fn("nginx:1"), Ok(("nginx", "1"))); + assert_eq!(test_fn("nginx:latest"), Ok(("nginx", "latest"))); + } } diff --git a/src/tags.rs b/src/tags.rs index e94969b..42aa524 100644 --- a/src/tags.rs +++ b/src/tags.rs @@ -1,5 +1,6 @@ use std::fmt; +use crate::repo; use chrono::DateTime; use serde::Deserialize; @@ -28,7 +29,7 @@ pub struct Tags { pub results: Vec, } -#[derive(Debug)] +#[derive(Debug, PartialEq)] pub enum Error { /// repo string contains an illegal character InvalidCharacter(char), @@ -84,18 +85,17 @@ impl Tags { } /// checks the repo name and may add a prefix for official images - pub fn check_repo(mut name: String) -> Result { - //check for right set of characters - if name.bytes().any(|c| !c.is_ascii()) { - return Err(Error::InvalidCharacter('a')); - } + pub fn check_repo(name: &str) -> Result { + let repo = match repo::split_tag_from_repo(name) { + Err(e) => return Err(Error::Converting(format!("{}", e))), + Ok((name, _)) => name, + }; - //check if need to inject "library" of given repo - let regex = regex::Regex::new(r".*/.*").unwrap(); - if !regex.is_match(&name) { - name.insert_str(0, "library/"); + match repo::split_repo_without_tag(name) { + Ok(repo::Repo::Project(s)) => Ok(format!("library/{}", s)), + Ok(_) => Ok(repo.to_string()), + Err(e) => Err(Error::Converting(format!("{}", e))), } - Ok(name) } /// returns tags of next page @@ -149,26 +149,14 @@ fn format_time_nice(time: chrono::Duration) -> String { #[cfg(test)] mod tests { - use crate::tags; + use crate::tags::{Error, Tags}; #[test] fn test_check_repo() { - let check_eq = |s, s2| { - assert_eq!(&tags::Tags::check_repo(String::from(s)).unwrap(), s2); - }; - let check_neq = |s, s2| { - assert_ne!(&tags::Tags::check_repo(String::from(s)).unwrap(), s2); - }; - let check_err = |s: &str| { - assert_eq!(tags::Tags::check_repo(String::from(s)).is_err(), true); - }; - - check_eq("nginx", "library/nginx"); - check_neq("nginx", "nginx"); - check_eq("rocketchat/rocket.chat", "rocketchat/rocket.chat"); - check_eq("mysql", "library/mysql"); - check_neq("mysql", "mysql"); - check_err("nginxä"); - check_err("nginx²"); - check_eq("selim13/automysqlbackup", "selim13/automysqlbackup"); + assert_eq!(Tags::check_repo("nginx").unwrap(), "library/nginx"); + assert_eq!(Tags::check_repo("library/nginx").unwrap(), "library/nginx"); + assert_eq!( + Tags::check_repo("rocketchat/rocket.chat").unwrap(), + "rocketchat/rocket.chat" + ); } } diff --git a/src/ui.rs b/src/ui.rs index 8f09daa..3605204 100644 --- a/src/ui.rs +++ b/src/ui.rs @@ -151,14 +151,14 @@ impl Ui { match ui.services.extract_repo() { Err(e) => ui.info.set_info(&format!("{}", e)), Ok(s) => { - let repo = match crate::tags::Tags::check_repo(s) { + let repo = match crate::tags::Tags::check_repo(&s) { Err(e) => { ui.info.set_info(&format!("{}", e)); continue; } Ok(s) => s, }; - ui.repo.set(repo); + ui.repo.set(repo.to_string()); ui.tags = tag_list::TagList::with_repo(ui.repo.get()); } } @@ -171,14 +171,14 @@ impl Ui { match ui.services.extract_repo() { Err(e) => ui.info.set_info(&format!("{}", e)), Ok(s) => { - let repo = match crate::tags::Tags::check_repo(s) { + let repo = match crate::tags::Tags::check_repo(&s) { Err(e) => { ui.info.set_info(&format!("{}", e)); continue; } Ok(s) => s, }; - ui.repo.set(repo); + ui.repo.set(repo.to_string()); ui.tags = tag_list::TagList::with_repo(ui.repo.get()); } }