added anyhow and thiserror; fixed clippy warnings; stopped creating switcher twice
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
This commit is contained in:
parent
8363896052
commit
8ab2690d17
28
Cargo.lock
generated
28
Cargo.lock
generated
@ -20,6 +20,12 @@ dependencies = [
|
|||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anyhow"
|
||||||
|
version = "1.0.59"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c91f1f46651137be86f3a2b9a8359f9ab421d04d941c62b5982e1ca21113adf9"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "atty"
|
name = "atty"
|
||||||
version = "0.2.14"
|
version = "0.2.14"
|
||||||
@ -675,6 +681,7 @@ dependencies = [
|
|||||||
name = "reel-moby"
|
name = "reel-moby"
|
||||||
version = "1.2.1"
|
version = "1.2.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
"chrono",
|
"chrono",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"regex",
|
"regex",
|
||||||
@ -683,6 +690,7 @@ dependencies = [
|
|||||||
"serde_json",
|
"serde_json",
|
||||||
"structopt",
|
"structopt",
|
||||||
"termion",
|
"termion",
|
||||||
|
"thiserror",
|
||||||
"tui",
|
"tui",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -921,6 +929,26 @@ dependencies = [
|
|||||||
"unicode-width",
|
"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]]
|
[[package]]
|
||||||
name = "time"
|
name = "time"
|
||||||
version = "0.1.44"
|
version = "0.1.44"
|
||||||
|
@ -16,6 +16,8 @@ termion = "1.5"
|
|||||||
regex = "1.5.4"
|
regex = "1.5.4"
|
||||||
lazy_static = "1.4.0"
|
lazy_static = "1.4.0"
|
||||||
structopt = "0.3.23"
|
structopt = "0.3.23"
|
||||||
|
thiserror = "1.0.32"
|
||||||
|
anyhow = "1.0.59"
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
lto = "yes"
|
lto = "yes"
|
||||||
|
13
src/main.rs
13
src/main.rs
@ -1,12 +1,13 @@
|
|||||||
use std::path::PathBuf;
|
|
||||||
use structopt::StructOpt;
|
|
||||||
|
|
||||||
mod common;
|
mod common;
|
||||||
mod repo;
|
mod repo;
|
||||||
mod repository;
|
mod repository;
|
||||||
mod ui;
|
mod ui;
|
||||||
mod widget;
|
mod widget;
|
||||||
|
|
||||||
|
use anyhow::Result;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
use structopt::StructOpt;
|
||||||
|
|
||||||
/// helps you searching or updating tags of your used docker images
|
/// helps you searching or updating tags of your used docker images
|
||||||
#[derive(StructOpt, Debug)]
|
#[derive(StructOpt, Debug)]
|
||||||
pub struct Opt {
|
pub struct Opt {
|
||||||
@ -19,8 +20,10 @@ pub struct Opt {
|
|||||||
repo: Option<String>,
|
repo: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() -> Result<()> {
|
||||||
//parse parameter
|
//parse parameter
|
||||||
let opt = Opt::from_args();
|
let opt = Opt::from_args();
|
||||||
ui::create_ui(&opt);
|
ui::create_ui(&opt)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -19,11 +19,11 @@ pub struct Images {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Images {
|
impl Images {
|
||||||
pub fn convert(&self) -> super::Tag {
|
pub fn from_tag(images: &Self) -> super::Tag {
|
||||||
super::Tag {
|
super::Tag {
|
||||||
name: self.tag_name.clone(),
|
name: images.tag_name.clone(),
|
||||||
last_updated: Some(self.last_updated.clone()),
|
last_updated: Some(images.last_updated.clone()),
|
||||||
details: self
|
details: images
|
||||||
.images
|
.images
|
||||||
.iter()
|
.iter()
|
||||||
.map(|d| super::TagDetails {
|
.map(|d| super::TagDetails {
|
||||||
@ -69,7 +69,7 @@ impl DockerHub {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Ok(super::Repo {
|
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,
|
next_page: tags.next_page,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -1,32 +1,24 @@
|
|||||||
mod dockerhub;
|
mod dockerhub;
|
||||||
|
|
||||||
use std::fmt;
|
|
||||||
|
|
||||||
use chrono::DateTime;
|
use chrono::DateTime;
|
||||||
|
use thiserror::Error;
|
||||||
|
|
||||||
use crate::common::display_duration_ext::DisplayDurationExt;
|
use crate::common::display_duration_ext::DisplayDurationExt;
|
||||||
use crate::repo;
|
use crate::repo;
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq, Error)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
/// couldn't fetch json with reqwest
|
/// couldn't fetch json with reqwest
|
||||||
|
#[error("Fetching error: {0}")]
|
||||||
Fetching(String),
|
Fetching(String),
|
||||||
/// a serde error
|
/// a serde error
|
||||||
|
#[error("Converting error: {0}")]
|
||||||
Converting(String),
|
Converting(String),
|
||||||
/// invalid repos show a valid json with 0 tags
|
/// invalid repos show a valid json with 0 tags
|
||||||
|
#[error("Given Repo does not exists or has 0 tags.")]
|
||||||
NoTagsFound,
|
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)]
|
#[derive(Clone, PartialEq)]
|
||||||
pub struct TagDetails {
|
pub struct TagDetails {
|
||||||
pub arch: Option<String>,
|
pub arch: Option<String>,
|
||||||
|
@ -1,17 +1,18 @@
|
|||||||
use std::{io, thread};
|
use anyhow::Result;
|
||||||
|
|
||||||
use crate::Opt;
|
|
||||||
use termion::event::Key;
|
use termion::event::Key;
|
||||||
use termion::raw::IntoRawMode;
|
use termion::raw::IntoRawMode;
|
||||||
use tui::backend::TermionBackend;
|
use tui::backend::TermionBackend;
|
||||||
use tui::layout::{Constraint, Direction, Layout};
|
use tui::layout::{Constraint, Direction, Layout};
|
||||||
use tui::Terminal;
|
use tui::Terminal;
|
||||||
|
|
||||||
|
use std::{io, thread};
|
||||||
|
|
||||||
use crate::repository;
|
use crate::repository;
|
||||||
use crate::widget::info;
|
use crate::widget::info;
|
||||||
use crate::widget::repo_entry;
|
use crate::widget::repo_entry;
|
||||||
use crate::widget::service_switcher;
|
use crate::widget::service_switcher;
|
||||||
use crate::widget::tag_list;
|
use crate::widget::tag_list;
|
||||||
|
use crate::Opt;
|
||||||
|
|
||||||
pub struct Ui {
|
pub struct Ui {
|
||||||
state: State,
|
state: State,
|
||||||
@ -53,14 +54,14 @@ impl std::iter::Iterator for State {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Ui {
|
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 repo_id = opt.repo.as_deref();
|
||||||
|
|
||||||
let mut ui = Ui {
|
let mut ui = Ui {
|
||||||
state: State::SelectService,
|
state: State::SelectService,
|
||||||
repo: repo_entry::RepoEntry::new(repo_id),
|
repo: repo_entry::RepoEntry::new(repo_id),
|
||||||
tags: tag_list::TagList::with_status("Tags are empty"),
|
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(),
|
details: crate::widget::details::Details::new(),
|
||||||
info: info::Info::new("Select image of edit Repository"),
|
info: info::Info::new("Select image of edit Repository"),
|
||||||
};
|
};
|
||||||
@ -70,9 +71,9 @@ impl Ui {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//setup tui
|
//setup tui
|
||||||
let stdout = io::stdout().into_raw_mode().unwrap();
|
let stdout = io::stdout().into_raw_mode()?;
|
||||||
let backend = TermionBackend::new(stdout);
|
let backend = TermionBackend::new(stdout);
|
||||||
let mut terminal = Terminal::new(backend).unwrap();
|
let mut terminal = Terminal::new(backend)?;
|
||||||
|
|
||||||
//setup input thread
|
//setup input thread
|
||||||
let receiver = super::spawn_stdin_channel();
|
let receiver = super::spawn_stdin_channel();
|
||||||
@ -80,34 +81,32 @@ impl Ui {
|
|||||||
//core interaction loop
|
//core interaction loop
|
||||||
'core: loop {
|
'core: loop {
|
||||||
//draw
|
//draw
|
||||||
terminal
|
terminal.draw(|rect| {
|
||||||
.draw(|rect| {
|
let chunks = Layout::default()
|
||||||
let chunks = Layout::default()
|
.direction(Direction::Vertical)
|
||||||
.direction(Direction::Vertical)
|
.constraints(
|
||||||
.constraints(
|
[
|
||||||
[
|
Constraint::Length(10),
|
||||||
Constraint::Length(10),
|
Constraint::Length(3),
|
||||||
Constraint::Length(3),
|
Constraint::Min(7),
|
||||||
Constraint::Min(7),
|
Constraint::Length(2),
|
||||||
Constraint::Length(2),
|
]
|
||||||
]
|
.as_ref(),
|
||||||
.as_ref(),
|
)
|
||||||
)
|
.split(rect.size());
|
||||||
.split(rect.size());
|
|
||||||
|
|
||||||
let (list, state) = ui.services.render(ui.state == State::SelectService);
|
let (list, state) = ui.services.render(ui.state == State::SelectService);
|
||||||
rect.render_stateful_widget(list, chunks[0], state);
|
rect.render_stateful_widget(list, chunks[0], state);
|
||||||
rect.render_widget(ui.repo.render(ui.state == State::EditRepo), chunks[1]);
|
rect.render_widget(ui.repo.render(ui.state == State::EditRepo), chunks[1]);
|
||||||
let (list, state) = ui.tags.render(ui.state == State::SelectTag);
|
let (list, state) = ui.tags.render(ui.state == State::SelectTag);
|
||||||
let more_chunks = Layout::default()
|
let more_chunks = Layout::default()
|
||||||
.direction(Direction::Horizontal)
|
.direction(Direction::Horizontal)
|
||||||
.constraints([Constraint::Min(15), Constraint::Length(28)].as_ref())
|
.constraints([Constraint::Min(15), Constraint::Length(28)].as_ref())
|
||||||
.split(chunks[2]);
|
.split(chunks[2]);
|
||||||
rect.render_stateful_widget(list, more_chunks[0], state);
|
rect.render_stateful_widget(list, more_chunks[0], state);
|
||||||
rect.render_widget(ui.details.render(), more_chunks[1]);
|
rect.render_widget(ui.details.render(), more_chunks[1]);
|
||||||
rect.render_widget(ui.info.render(), chunks[3]);
|
rect.render_widget(ui.info.render(), chunks[3]);
|
||||||
})
|
})?;
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
//handle input
|
//handle input
|
||||||
match receiver.try_recv() {
|
match receiver.try_recv() {
|
||||||
@ -219,6 +218,8 @@ impl Ui {
|
|||||||
thread::sleep(std::time::Duration::from_millis(32));
|
thread::sleep(std::time::Duration::from_millis(32));
|
||||||
}
|
}
|
||||||
|
|
||||||
terminal.clear().unwrap();
|
terminal.clear()?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,20 +1,23 @@
|
|||||||
mod default;
|
mod default;
|
||||||
mod no_yaml;
|
mod no_yaml;
|
||||||
|
|
||||||
|
use anyhow::Result;
|
||||||
|
use termion::input::TermRead;
|
||||||
|
|
||||||
|
use crate::widget::service_switcher;
|
||||||
|
use crate::Opt;
|
||||||
|
|
||||||
use std::sync::mpsc;
|
use std::sync::mpsc;
|
||||||
use std::{io, thread};
|
use std::{io, thread};
|
||||||
|
|
||||||
use crate::Opt;
|
pub fn create_ui(opt: &Opt) -> Result<()> {
|
||||||
use termion::input::TermRead;
|
|
||||||
|
|
||||||
use crate::widget::service_switcher;
|
|
||||||
|
|
||||||
pub fn create_ui(opt: &Opt) {
|
|
||||||
let service_result = service_switcher::ServiceSwitcher::new(&opt.file);
|
let service_result = service_switcher::ServiceSwitcher::new(&opt.file);
|
||||||
match service_result {
|
match service_result {
|
||||||
None => no_yaml::NoYaml::run(opt),
|
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
|
/// create a thread for catching input and send them to core loop
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
use std::{io, thread};
|
use anyhow::Result;
|
||||||
|
|
||||||
use termion::event::Key;
|
use termion::event::Key;
|
||||||
use termion::raw::IntoRawMode;
|
use termion::raw::IntoRawMode;
|
||||||
use tui::backend::TermionBackend;
|
use tui::backend::TermionBackend;
|
||||||
use tui::layout::{Constraint, Direction, Layout};
|
use tui::layout::{Constraint, Direction, Layout};
|
||||||
use tui::Terminal;
|
use tui::Terminal;
|
||||||
|
|
||||||
|
use std::{io, thread};
|
||||||
|
|
||||||
use crate::widget::details;
|
use crate::widget::details;
|
||||||
use crate::widget::info;
|
use crate::widget::info;
|
||||||
use crate::widget::repo_entry;
|
use crate::widget::repo_entry;
|
||||||
@ -48,7 +49,7 @@ pub struct NoYaml {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl NoYaml {
|
impl NoYaml {
|
||||||
pub fn run(opt: &Opt) {
|
pub fn run(opt: &Opt) -> Result<()> {
|
||||||
let repo_id = opt.repo.as_deref();
|
let repo_id = opt.repo.as_deref();
|
||||||
|
|
||||||
let mut ui = NoYaml {
|
let mut ui = NoYaml {
|
||||||
@ -65,9 +66,9 @@ impl NoYaml {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//setup tui
|
//setup tui
|
||||||
let stdout = io::stdout().into_raw_mode().unwrap();
|
let stdout = io::stdout().into_raw_mode()?;
|
||||||
let backend = TermionBackend::new(stdout);
|
let backend = TermionBackend::new(stdout);
|
||||||
let mut terminal = Terminal::new(backend).unwrap();
|
let mut terminal = Terminal::new(backend)?;
|
||||||
|
|
||||||
//setup input thread
|
//setup input thread
|
||||||
let receiver = super::spawn_stdin_channel();
|
let receiver = super::spawn_stdin_channel();
|
||||||
@ -75,31 +76,29 @@ impl NoYaml {
|
|||||||
//core interaction loop
|
//core interaction loop
|
||||||
'core: loop {
|
'core: loop {
|
||||||
//draw
|
//draw
|
||||||
terminal
|
terminal.draw(|rect| {
|
||||||
.draw(|rect| {
|
let chunks = Layout::default()
|
||||||
let chunks = Layout::default()
|
.direction(Direction::Vertical)
|
||||||
.direction(Direction::Vertical)
|
.constraints(
|
||||||
.constraints(
|
[
|
||||||
[
|
Constraint::Length(3),
|
||||||
Constraint::Length(3),
|
Constraint::Min(7),
|
||||||
Constraint::Min(7),
|
Constraint::Length(2),
|
||||||
Constraint::Length(2),
|
]
|
||||||
]
|
.as_ref(),
|
||||||
.as_ref(),
|
)
|
||||||
)
|
.split(rect.size());
|
||||||
.split(rect.size());
|
|
||||||
|
|
||||||
rect.render_widget(ui.repo.render(ui.state == State::EditRepo), chunks[0]);
|
rect.render_widget(ui.repo.render(ui.state == State::EditRepo), chunks[0]);
|
||||||
let (list, state) = ui.tags.render(ui.state == State::SelectTag);
|
let (list, state) = ui.tags.render(ui.state == State::SelectTag);
|
||||||
let more_chunks = Layout::default()
|
let more_chunks = Layout::default()
|
||||||
.direction(Direction::Horizontal)
|
.direction(Direction::Horizontal)
|
||||||
.constraints([Constraint::Min(15), Constraint::Length(28)].as_ref())
|
.constraints([Constraint::Min(15), Constraint::Length(28)].as_ref())
|
||||||
.split(chunks[1]);
|
.split(chunks[1]);
|
||||||
rect.render_stateful_widget(list, more_chunks[0], state);
|
rect.render_stateful_widget(list, more_chunks[0], state);
|
||||||
rect.render_widget(ui.details.render(), more_chunks[1]);
|
rect.render_widget(ui.details.render(), more_chunks[1]);
|
||||||
rect.render_widget(ui.info.render(), chunks[2]);
|
rect.render_widget(ui.info.render(), chunks[2]);
|
||||||
})
|
})?;
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
//handle input
|
//handle input
|
||||||
match receiver.try_recv() {
|
match receiver.try_recv() {
|
||||||
@ -156,6 +155,7 @@ impl NoYaml {
|
|||||||
thread::sleep(std::time::Duration::from_millis(32));
|
thread::sleep(std::time::Duration::from_millis(32));
|
||||||
}
|
}
|
||||||
|
|
||||||
terminal.clear().unwrap();
|
terminal.clear()?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user