added anyhow and thiserror; fixed clippy warnings; stopped creating switcher twice
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful

This commit is contained in:
Thomas Eppers 2022-08-04 15:37:19 +02:00
parent 8363896052
commit 8ab2690d17
8 changed files with 125 additions and 96 deletions

28
Cargo.lock generated
View File

@ -20,6 +20,12 @@ dependencies = [
"winapi",
]
[[package]]
name = "anyhow"
version = "1.0.59"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c91f1f46651137be86f3a2b9a8359f9ab421d04d941c62b5982e1ca21113adf9"
[[package]]
name = "atty"
version = "0.2.14"
@ -675,6 +681,7 @@ dependencies = [
name = "reel-moby"
version = "1.2.1"
dependencies = [
"anyhow",
"chrono",
"lazy_static",
"regex",
@ -683,6 +690,7 @@ dependencies = [
"serde_json",
"structopt",
"termion",
"thiserror",
"tui",
]
@ -921,6 +929,26 @@ dependencies = [
"unicode-width",
]
[[package]]
name = "thiserror"
version = "1.0.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f5f6586b7f764adc0231f4c79be7b920e766bb2f3e51b3661cdb263828f19994"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "12bafc5b54507e0149cdf1b145a5d80ab80a90bcd9275df43d4fff68460f6c21"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "time"
version = "0.1.44"

View File

@ -16,6 +16,8 @@ termion = "1.5"
regex = "1.5.4"
lazy_static = "1.4.0"
structopt = "0.3.23"
thiserror = "1.0.32"
anyhow = "1.0.59"
[profile.release]
lto = "yes"

View File

@ -1,12 +1,13 @@
use std::path::PathBuf;
use structopt::StructOpt;
mod common;
mod repo;
mod repository;
mod ui;
mod widget;
use anyhow::Result;
use std::path::PathBuf;
use structopt::StructOpt;
/// helps you searching or updating tags of your used docker images
#[derive(StructOpt, Debug)]
pub struct Opt {
@ -19,8 +20,10 @@ pub struct Opt {
repo: Option<String>,
}
fn main() {
fn main() -> Result<()> {
//parse parameter
let opt = Opt::from_args();
ui::create_ui(&opt);
ui::create_ui(&opt)?;
Ok(())
}

View File

@ -19,11 +19,11 @@ pub struct Images {
}
impl Images {
pub fn convert(&self) -> super::Tag {
pub fn from_tag(images: &Self) -> super::Tag {
super::Tag {
name: self.tag_name.clone(),
last_updated: Some(self.last_updated.clone()),
details: self
name: images.tag_name.clone(),
last_updated: Some(images.last_updated.clone()),
details: images
.images
.iter()
.map(|d| super::TagDetails {
@ -69,7 +69,7 @@ impl DockerHub {
}
Ok(super::Repo {
tags: tags.results.iter().map(|t| t.convert()).collect(),
tags: tags.results.iter().map(Images::from_tag).collect(),
next_page: tags.next_page,
})
}

View File

@ -1,32 +1,24 @@
mod dockerhub;
use std::fmt;
use chrono::DateTime;
use thiserror::Error;
use crate::common::display_duration_ext::DisplayDurationExt;
use crate::repo;
#[derive(Debug, PartialEq)]
#[derive(Debug, PartialEq, Error)]
pub enum Error {
/// couldn't fetch json with reqwest
#[error("Fetching error: {0}")]
Fetching(String),
/// a serde error
#[error("Converting error: {0}")]
Converting(String),
/// invalid repos show a valid json with 0 tags
#[error("Given Repo does not exists or has 0 tags.")]
NoTagsFound,
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Error::Fetching(s) => write!(f, "Fetching error: {}", s),
Error::Converting(s) => write!(f, "Converting error: {}", s),
Error::NoTagsFound => write!(f, "Given Repo has 0 tags. Is it valid?"),
}
}
}
#[derive(Clone, PartialEq)]
pub struct TagDetails {
pub arch: Option<String>,

View File

@ -1,17 +1,18 @@
use std::{io, thread};
use crate::Opt;
use anyhow::Result;
use termion::event::Key;
use termion::raw::IntoRawMode;
use tui::backend::TermionBackend;
use tui::layout::{Constraint, Direction, Layout};
use tui::Terminal;
use std::{io, thread};
use crate::repository;
use crate::widget::info;
use crate::widget::repo_entry;
use crate::widget::service_switcher;
use crate::widget::tag_list;
use crate::Opt;
pub struct Ui {
state: State,
@ -53,14 +54,14 @@ impl std::iter::Iterator for State {
}
impl Ui {
pub fn run(opt: &Opt) {
pub fn run(opt: &Opt, switcher: service_switcher::ServiceSwitcher) -> Result<()> {
let repo_id = opt.repo.as_deref();
let mut ui = Ui {
state: State::SelectService,
repo: repo_entry::RepoEntry::new(repo_id),
tags: tag_list::TagList::with_status("Tags are empty"),
services: service_switcher::ServiceSwitcher::new(&opt.file).unwrap(),
services: switcher,
details: crate::widget::details::Details::new(),
info: info::Info::new("Select image of edit Repository"),
};
@ -70,9 +71,9 @@ impl Ui {
}
//setup tui
let stdout = io::stdout().into_raw_mode().unwrap();
let stdout = io::stdout().into_raw_mode()?;
let backend = TermionBackend::new(stdout);
let mut terminal = Terminal::new(backend).unwrap();
let mut terminal = Terminal::new(backend)?;
//setup input thread
let receiver = super::spawn_stdin_channel();
@ -80,8 +81,7 @@ impl Ui {
//core interaction loop
'core: loop {
//draw
terminal
.draw(|rect| {
terminal.draw(|rect| {
let chunks = Layout::default()
.direction(Direction::Vertical)
.constraints(
@ -106,8 +106,7 @@ impl Ui {
rect.render_stateful_widget(list, more_chunks[0], state);
rect.render_widget(ui.details.render(), more_chunks[1]);
rect.render_widget(ui.info.render(), chunks[3]);
})
.unwrap();
})?;
//handle input
match receiver.try_recv() {
@ -219,6 +218,8 @@ impl Ui {
thread::sleep(std::time::Duration::from_millis(32));
}
terminal.clear().unwrap();
terminal.clear()?;
Ok(())
}
}

View File

@ -1,20 +1,23 @@
mod default;
mod no_yaml;
use anyhow::Result;
use termion::input::TermRead;
use crate::widget::service_switcher;
use crate::Opt;
use std::sync::mpsc;
use std::{io, thread};
use crate::Opt;
use termion::input::TermRead;
use crate::widget::service_switcher;
pub fn create_ui(opt: &Opt) {
pub fn create_ui(opt: &Opt) -> Result<()> {
let service_result = service_switcher::ServiceSwitcher::new(&opt.file);
match service_result {
None => no_yaml::NoYaml::run(opt),
Some(_) => default::Ui::run(opt),
}
Some(switcher) => default::Ui::run(opt, switcher),
}?;
Ok(())
}
/// create a thread for catching input and send them to core loop

View File

@ -1,11 +1,12 @@
use std::{io, thread};
use anyhow::Result;
use termion::event::Key;
use termion::raw::IntoRawMode;
use tui::backend::TermionBackend;
use tui::layout::{Constraint, Direction, Layout};
use tui::Terminal;
use std::{io, thread};
use crate::widget::details;
use crate::widget::info;
use crate::widget::repo_entry;
@ -48,7 +49,7 @@ pub struct NoYaml {
}
impl NoYaml {
pub fn run(opt: &Opt) {
pub fn run(opt: &Opt) -> Result<()> {
let repo_id = opt.repo.as_deref();
let mut ui = NoYaml {
@ -65,9 +66,9 @@ impl NoYaml {
}
//setup tui
let stdout = io::stdout().into_raw_mode().unwrap();
let stdout = io::stdout().into_raw_mode()?;
let backend = TermionBackend::new(stdout);
let mut terminal = Terminal::new(backend).unwrap();
let mut terminal = Terminal::new(backend)?;
//setup input thread
let receiver = super::spawn_stdin_channel();
@ -75,8 +76,7 @@ impl NoYaml {
//core interaction loop
'core: loop {
//draw
terminal
.draw(|rect| {
terminal.draw(|rect| {
let chunks = Layout::default()
.direction(Direction::Vertical)
.constraints(
@ -98,8 +98,7 @@ impl NoYaml {
rect.render_stateful_widget(list, more_chunks[0], state);
rect.render_widget(ui.details.render(), more_chunks[1]);
rect.render_widget(ui.info.render(), chunks[2]);
})
.unwrap();
})?;
//handle input
match receiver.try_recv() {
@ -156,6 +155,7 @@ impl NoYaml {
thread::sleep(std::time::Duration::from_millis(32));
}
terminal.clear().unwrap();
terminal.clear()?;
Ok(())
}
}