Skip to content

Refactor search #30

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
134 changes: 57 additions & 77 deletions src/cmd/search.rs
Original file line number Diff line number Diff line change
@@ -1,94 +1,74 @@
mod groups_cmd;
mod projects_cmd;
mod users_cmd;
pub(crate) mod commands;
mod groups;
mod projects;
mod users;

use std::io::{Error, ErrorKind};

use clap::{ArgMatches, Command};
use std::{
collections::HashMap,
fmt::{self, Display, Formatter},
io::{Error, Result},
str::FromStr,
};

use gitlab::Gitlab;

use crate::{
args::{gitlab_token::ArgGitlabToken, gitlab_url::ArgGitlabUrl, Args},
cmd::Cmd,
};
use self::{groups::Groups, projects::Projects, users::Users};

/// Register search cmd
pub(crate) fn add_search_cmd() -> Command<'static> {
return Command::new("search")
.aliases(&["s", "find"])
.about("Search for GitLab entities")
.arg(ArgGitlabToken::add())
.arg(ArgGitlabUrl::add())
.arg_required_else_help(true)
.subcommand(projects_cmd::find_projects())
.subcommand(users_cmd::find_users())
.subcommand(groups_cmd::find_groups());
pub(crate) trait SearchEntity {
fn search(&self, query: &str) -> Result<()>;
}

pub(crate) struct SearchCmd<'a> {
// search_string: String,
search_sub: Option<(&'a str, &'a ArgMatches)>,
gitlab_client: Gitlab,
pub(crate) struct SearchService<'a> {
entities: HashMap<EntityName, Box<dyn SearchEntity + 'a>>,
}

pub(crate) fn prepare<'a>(sub_matches: &'a ArgMatches) -> Result<impl Cmd<'a>, Error> {
let gitlab_token = match ArgGitlabToken::parse(sub_matches) {
Ok(arg) => arg.value(),
Err(err) => return Err(err),
};
let gitlab_url = match ArgGitlabUrl::parse(sub_matches) {
Ok(arg) => arg.value(),
Err(err) => return Err(err),
};
impl<'a> SearchService<'a> {
pub fn new(gitlab_client: &'a Gitlab) -> Self {
let mut entities: HashMap<EntityName, Box<dyn SearchEntity>> = HashMap::new();
entities.insert(EntityName::PROJECTS, Box::new(Projects::new(gitlab_client)));
entities.insert(EntityName::GROUPS, Box::new(Groups::new(gitlab_client)));
entities.insert(EntityName::USERS, Box::new(Users::new(gitlab_client)));
SearchService { entities }
}

// Connect to gitlab
let gitlab_client: Gitlab = match Gitlab::new(
gitlab_url.to_string(),
gitlab_token.to_string(),
) {
Ok(g) => g,
Err(_err) => return Err(Error::new(ErrorKind::Other, _err)),
};
pub fn search(&self, entity_name: &str, query: &str) -> Result<()> {
let entity_name = EntityName::from_str(entity_name)?;
let entity = self.entities.get(&entity_name).ok_or_else(|| {
Error::new(
std::io::ErrorKind::NotFound,
format!("Could not resolve entity with name {entity_name}"),
)
})?;

// Get search subcommand
let search_sub = sub_matches.subcommand();
entity.search(query)
}
}

Ok(SearchCmd {
search_sub,
gitlab_client,
})
#[derive(Hash, PartialEq, Eq, Debug)]
pub(crate) enum EntityName {
GROUPS,
PROJECTS,
USERS,
}

impl<'a> Cmd<'a> for SearchCmd<'a> {
fn exec(&self) -> Result<(), Error> {
let result;
match self.search_sub {
Some(("users", sub_matches)) => {
result = match users_cmd::prepare(sub_matches, &self.gitlab_client) {
Ok(cmd) => cmd.exec(),
Err(err) => Err(err),
};
}
Some(("projects", sub_matches)) => {
result = match projects_cmd::prepare(sub_matches, &self.gitlab_client) {
Ok(cmd) => cmd.exec(),
Err(err) => Err(err),
};
}
Some(("groups", sub_matches)) => {
result = match groups_cmd::prepare(sub_matches, &self.gitlab_client) {
Ok(cmd) => cmd.exec(),
Err(err) => Err(err),
};
}
_ => {
return Err(Error::new(
std::io::ErrorKind::InvalidInput,
"You should specify what you are looking for, please use help",
));
}
impl FromStr for EntityName {
type Err = Error;

fn from_str(s: &str) -> Result<EntityName> {
match s {
"groups" => Ok(Self::GROUPS),
"projects" => Ok(Self::PROJECTS),
"users" => Ok(Self::USERS),
name => Err(Error::new(
std::io::ErrorKind::InvalidInput,
format!("Entity with name {name} does not exist"),
)),
}
return result;
}
}

impl Display for EntityName {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "{:?}", self)
}
}
35 changes: 35 additions & 0 deletions src/cmd/search/commands.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
use crate::args::{gitlab_token::ArgGitlabToken, gitlab_url::ArgGitlabUrl, Args};
use clap::{arg, Command};

pub(crate) fn add_search_cmd() -> Command<'static> {
return Command::new("search")
.aliases(&["s", "find"])
.about("Search for GitLab entities")
.arg(ArgGitlabToken::add())
.arg(ArgGitlabUrl::add())
.arg_required_else_help(true)
.subcommand(add_search_projects_cmd())
.subcommand(add_search_users_cmd())
.subcommand(add_search_groups_cmd());
}

fn add_search_projects_cmd() -> Command<'static> {
return Command::new("projects")
.about("Look for GitLab projects")
.aliases(&["p", "project"])
.arg(arg!(<SEARCH> "What you are looking for, mate?"));
}

fn add_search_users_cmd() -> Command<'static> {
return Command::new("users")
.about("Look for GitLab users")
.aliases(&["u", "user"])
.arg(arg!(<SEARCH> "What you are looking for, mate?"));
}

fn add_search_groups_cmd() -> Command<'static> {
return Command::new("groups")
.about("Look for GitLab groups")
.aliases(&["g", "group"])
.arg(arg!(<SEARCH> "What you are looking for, mate?"));
}
42 changes: 42 additions & 0 deletions src/cmd/search/groups.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
use std::io::{Error, ErrorKind, Result};

use gitlab::{
api::{groups, Query},
Gitlab,
};
use tabled::Table;

use crate::{
gitlab::Group,
output::{out_message::OutMessage, out_spinner::OutSpinner},
};

use super::SearchEntity;

pub(crate) struct Groups<'a> {
gitlab_client: &'a Gitlab,
}

impl<'a> Groups<'a> {
pub fn new(gitlab_client: &'a Gitlab) -> Self {
Groups { gitlab_client }
}
}

impl<'a> SearchEntity for Groups<'a> {
fn search(&self, query: &str) -> Result<()> {
let spinner = OutSpinner::spinner_start("Looking for groups".to_string());
let groups = match groups::Groups::builder().search(query).build() {
Ok(q) => q,
Err(err) => {
spinner.spinner_failure(err.to_string());
return Err(Error::new(ErrorKind::ConnectionRefused, err));
}
};
let output: Vec<Group> = groups.query(self.gitlab_client).unwrap();
spinner.spinner_success("That's what we've got for ya".to_string());
let table = Table::new(&output);
OutMessage::message_empty(format!("{}", table).as_str());
Ok(())
}
}
64 changes: 0 additions & 64 deletions src/cmd/search/groups_cmd.rs

This file was deleted.

42 changes: 42 additions & 0 deletions src/cmd/search/projects.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
use std::io::{Error, ErrorKind, Result};

use gitlab::{
api::{projects, Query},
Gitlab,
};
use tabled::Table;

use crate::{
gitlab::Project,
output::{out_message::OutMessage, out_spinner::OutSpinner},
};

use super::SearchEntity;

pub(crate) struct Projects<'a> {
gitlab_client: &'a Gitlab,
}

impl<'a> Projects<'a> {
pub fn new(gitlab_client: &'a Gitlab) -> Self {
Projects { gitlab_client }
}
}

impl<'a> SearchEntity for Projects<'a> {
fn search(&self, query: &str) -> Result<()> {
let spinner = OutSpinner::spinner_start("Looking for projects".to_string());
let projects = match projects::Projects::builder().search(query).build() {
Ok(q) => q,
Err(err) => {
spinner.spinner_failure(err.to_string());
return Err(Error::new(ErrorKind::ConnectionRefused, err));
}
};
let output: Vec<Project> = projects.query(self.gitlab_client).unwrap();
spinner.spinner_success("That's what we've got for ya".to_string());
let table = Table::new(&output);
OutMessage::message_empty(format!("{}", table).as_str());
Ok(())
}
}
Loading