Skip to content

Commit ff303bb

Browse files
committed
ready
1 parent 4d203d2 commit ff303bb

File tree

9 files changed

+254
-308
lines changed

9 files changed

+254
-308
lines changed

src/cmd/search.rs

+57-77
Original file line numberDiff line numberDiff line change
@@ -1,94 +1,74 @@
1-
mod groups_cmd;
2-
mod projects_cmd;
3-
mod users_cmd;
1+
pub(crate) mod commands;
2+
mod groups;
3+
mod projects;
4+
mod users;
45

5-
use std::io::{Error, ErrorKind};
6-
7-
use clap::{ArgMatches, Command};
6+
use std::{
7+
collections::HashMap,
8+
fmt::{self, Display, Formatter},
9+
io::{Error, Result},
10+
str::FromStr,
11+
};
812

913
use gitlab::Gitlab;
1014

11-
use crate::{
12-
args::{gitlab_token::ArgGitlabToken, gitlab_url::ArgGitlabUrl, Args},
13-
cmd::Cmd,
14-
};
15+
use self::{groups::Groups, projects::Projects, users::Users};
1516

16-
/// Register search cmd
17-
pub(crate) fn add_search_cmd() -> Command<'static> {
18-
return Command::new("search")
19-
.aliases(&["s", "find"])
20-
.about("Search for GitLab entities")
21-
.arg(ArgGitlabToken::add())
22-
.arg(ArgGitlabUrl::add())
23-
.arg_required_else_help(true)
24-
.subcommand(projects_cmd::find_projects())
25-
.subcommand(users_cmd::find_users())
26-
.subcommand(groups_cmd::find_groups());
17+
pub(crate) trait SearchEntity {
18+
fn search(&self, query: &str) -> Result<()>;
2719
}
2820

29-
pub(crate) struct SearchCmd<'a> {
30-
// search_string: String,
31-
search_sub: Option<(&'a str, &'a ArgMatches)>,
32-
gitlab_client: Gitlab,
21+
pub(crate) struct SearchService<'a> {
22+
entities: HashMap<EntityName, Box<dyn SearchEntity + 'a>>,
3323
}
3424

35-
pub(crate) fn prepare<'a>(sub_matches: &'a ArgMatches) -> Result<impl Cmd<'a>, Error> {
36-
let gitlab_token = match ArgGitlabToken::parse(sub_matches) {
37-
Ok(arg) => arg.value(),
38-
Err(err) => return Err(err),
39-
};
40-
let gitlab_url = match ArgGitlabUrl::parse(sub_matches) {
41-
Ok(arg) => arg.value(),
42-
Err(err) => return Err(err),
43-
};
25+
impl<'a> SearchService<'a> {
26+
pub fn new(gitlab_client: &'a Gitlab) -> Self {
27+
let mut entities: HashMap<EntityName, Box<dyn SearchEntity>> = HashMap::new();
28+
entities.insert(EntityName::PROJECTS, Box::new(Projects::new(gitlab_client)));
29+
entities.insert(EntityName::GROUPS, Box::new(Groups::new(gitlab_client)));
30+
entities.insert(EntityName::USERS, Box::new(Users::new(gitlab_client)));
31+
SearchService { entities }
32+
}
4433

45-
// Connect to gitlab
46-
let gitlab_client: Gitlab = match Gitlab::new(
47-
gitlab_url.to_string(),
48-
gitlab_token.to_string(),
49-
) {
50-
Ok(g) => g,
51-
Err(_err) => return Err(Error::new(ErrorKind::Other, _err)),
52-
};
34+
pub fn search(&self, entity_name: &str, query: &str) -> Result<()> {
35+
let entity_name = EntityName::from_str(entity_name)?;
36+
let entity = self.entities.get(&entity_name).ok_or_else(|| {
37+
Error::new(
38+
std::io::ErrorKind::NotFound,
39+
format!("Could not resolve entity with name {entity_name}"),
40+
)
41+
})?;
5342

54-
// Get search subcommand
55-
let search_sub = sub_matches.subcommand();
43+
entity.search(query)
44+
}
45+
}
5646

57-
Ok(SearchCmd {
58-
search_sub,
59-
gitlab_client,
60-
})
47+
#[derive(Hash, PartialEq, Eq, Debug)]
48+
pub(crate) enum EntityName {
49+
GROUPS,
50+
PROJECTS,
51+
USERS,
6152
}
6253

63-
impl<'a> Cmd<'a> for SearchCmd<'a> {
64-
fn exec(&self) -> Result<(), Error> {
65-
let result;
66-
match self.search_sub {
67-
Some(("users", sub_matches)) => {
68-
result = match users_cmd::prepare(sub_matches, &self.gitlab_client) {
69-
Ok(cmd) => cmd.exec(),
70-
Err(err) => Err(err),
71-
};
72-
}
73-
Some(("projects", sub_matches)) => {
74-
result = match projects_cmd::prepare(sub_matches, &self.gitlab_client) {
75-
Ok(cmd) => cmd.exec(),
76-
Err(err) => Err(err),
77-
};
78-
}
79-
Some(("groups", sub_matches)) => {
80-
result = match groups_cmd::prepare(sub_matches, &self.gitlab_client) {
81-
Ok(cmd) => cmd.exec(),
82-
Err(err) => Err(err),
83-
};
84-
}
85-
_ => {
86-
return Err(Error::new(
87-
std::io::ErrorKind::InvalidInput,
88-
"You should specify what you are looking for, please use help",
89-
));
90-
}
54+
impl FromStr for EntityName {
55+
type Err = Error;
56+
57+
fn from_str(s: &str) -> Result<EntityName> {
58+
match s {
59+
"groups" => Ok(Self::GROUPS),
60+
"projects" => Ok(Self::PROJECTS),
61+
"users" => Ok(Self::USERS),
62+
name => Err(Error::new(
63+
std::io::ErrorKind::InvalidInput,
64+
format!("Entity with name {name} does not exist"),
65+
)),
9166
}
92-
return result;
67+
}
68+
}
69+
70+
impl Display for EntityName {
71+
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
72+
write!(f, "{:?}", self)
9373
}
9474
}

src/cmd/search/commands.rs

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
use crate::args::{gitlab_token::ArgGitlabToken, gitlab_url::ArgGitlabUrl, Args};
2+
use clap::{arg, Command};
3+
4+
pub(crate) fn add_search_cmd() -> Command<'static> {
5+
return Command::new("search")
6+
.aliases(&["s", "find"])
7+
.about("Search for GitLab entities")
8+
.arg(ArgGitlabToken::add())
9+
.arg(ArgGitlabUrl::add())
10+
.arg_required_else_help(true)
11+
.subcommand(add_search_projects_cmd())
12+
.subcommand(add_search_users_cmd())
13+
.subcommand(add_search_groups_cmd());
14+
}
15+
16+
fn add_search_projects_cmd() -> Command<'static> {
17+
return Command::new("projects")
18+
.about("Look for GitLab projects")
19+
.aliases(&["p", "project"])
20+
.arg(arg!(<SEARCH> "What you are looking for, mate?"));
21+
}
22+
23+
fn add_search_users_cmd() -> Command<'static> {
24+
return Command::new("users")
25+
.about("Look for GitLab users")
26+
.aliases(&["u", "user"])
27+
.arg(arg!(<SEARCH> "What you are looking for, mate?"));
28+
}
29+
30+
fn add_search_groups_cmd() -> Command<'static> {
31+
return Command::new("groups")
32+
.about("Look for GitLab groups")
33+
.aliases(&["g", "group"])
34+
.arg(arg!(<SEARCH> "What you are looking for, mate?"));
35+
}

src/cmd/search/groups.rs

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
use std::io::{Error, ErrorKind, Result};
2+
3+
use gitlab::{
4+
api::{groups, Query},
5+
Gitlab,
6+
};
7+
use tabled::Table;
8+
9+
use crate::{
10+
gitlab::Group,
11+
output::{out_message::OutMessage, out_spinner::OutSpinner},
12+
};
13+
14+
use super::SearchEntity;
15+
16+
pub(crate) struct Groups<'a> {
17+
gitlab_client: &'a Gitlab,
18+
}
19+
20+
impl<'a> Groups<'a> {
21+
pub fn new(gitlab_client: &'a Gitlab) -> Self {
22+
Groups { gitlab_client }
23+
}
24+
}
25+
26+
impl<'a> SearchEntity for Groups<'a> {
27+
fn search(&self, query: &str) -> Result<()> {
28+
let spinner = OutSpinner::spinner_start("Looking for groups".to_string());
29+
let groups = match groups::Groups::builder().search(query).build() {
30+
Ok(q) => q,
31+
Err(err) => {
32+
spinner.spinner_failure(err.to_string());
33+
return Err(Error::new(ErrorKind::ConnectionRefused, err));
34+
}
35+
};
36+
let output: Vec<Group> = groups.query(self.gitlab_client).unwrap();
37+
spinner.spinner_success("That's what we've got for ya".to_string());
38+
let table = Table::new(&output);
39+
OutMessage::message_empty(format!("{}", table).as_str());
40+
Ok(())
41+
}
42+
}

src/cmd/search/groups_cmd.rs

-64
This file was deleted.

src/cmd/search/projects.rs

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
use std::io::{Error, ErrorKind, Result};
2+
3+
use gitlab::{
4+
api::{projects, Query},
5+
Gitlab,
6+
};
7+
use tabled::Table;
8+
9+
use crate::{
10+
gitlab::Project,
11+
output::{out_message::OutMessage, out_spinner::OutSpinner},
12+
};
13+
14+
use super::SearchEntity;
15+
16+
pub(crate) struct Projects<'a> {
17+
gitlab_client: &'a Gitlab,
18+
}
19+
20+
impl<'a> Projects<'a> {
21+
pub fn new(gitlab_client: &'a Gitlab) -> Self {
22+
Projects { gitlab_client }
23+
}
24+
}
25+
26+
impl<'a> SearchEntity for Projects<'a> {
27+
fn search(&self, query: &str) -> Result<()> {
28+
let spinner = OutSpinner::spinner_start("Looking for projects".to_string());
29+
let projects = match projects::Projects::builder().search(query).build() {
30+
Ok(q) => q,
31+
Err(err) => {
32+
spinner.spinner_failure(err.to_string());
33+
return Err(Error::new(ErrorKind::ConnectionRefused, err));
34+
}
35+
};
36+
let output: Vec<Project> = projects.query(self.gitlab_client).unwrap();
37+
spinner.spinner_success("That's what we've got for ya".to_string());
38+
let table = Table::new(&output);
39+
OutMessage::message_empty(format!("{}", table).as_str());
40+
Ok(())
41+
}
42+
}

0 commit comments

Comments
 (0)