Skip to main content

grp_core/common/repos/
list.rs

1
2
3use futures::future::join_all;
4
5use crate::animation::Animation;
6use crate::config::Config;
7use crate::platform::Platform;
8use crate::error::structs::Error;
9use crate::common::pagination::pagination;
10use crate::common::structs::{Context, Repo, RequestType};
11
12impl Platform {
13    /// list all the repos for the given owner, if not present, returns all the repos for the default user (config).
14    /// 
15    /// # Return
16    /// a tuple with:
17    /// 1. `Vec<Repo>` a list with the repos 
18    /// 2. `Option<Error>` a `grp_core::Error` containing the detail of the error, if this error is present, the list of repos is empty.
19    /// 3. `Vec<Error>` a list of `grp_core::Error` that contains a list of errors if something happen during the paggination.
20    /// 
21    /// ## Why is this?
22    /// a better solution with yield is planned, but for know this is the best i could do.
23    pub async fn list_repos<T: Into<String>, A: Animation + ?Sized>(&self,
24        owner: Option<T>, 
25        config: &Config,
26        animation: &Box<A>
27    ) -> (Vec<Repo>, Option<Error>, Vec<Error>) {
28        let header_map = self.get_auth_header(&config.token);
29        let owner = owner.map(|o| o.into());
30        let owner = owner.unwrap_or(config.user.clone());
31        
32        animation.change_message("getting user type");
33        
34        let user_type = match self.get_user_type(&owner, &config).await {
35            Ok(ut) => ut,
36            Err(e) => return (Vec::new(), Some(e), vec![])
37        };
38        
39        animation.change_message("fetching repositories...");
40        
41        let url = self.url_list_repos(&user_type, &config.endpoint).await;
42        let (responses, error) = pagination(url, header_map).await;
43        
44        let responses: Vec<_> = responses.into_iter()
45            .map(|response| {
46                let context = Context {
47                    request_type: RequestType::List,
48                    owner: Some(user_type.get_user().name),
49                    repo: None,
50                    additional: None,
51                };
52                
53                self.unwrap(
54                    response, "Failed to fetch repositories",
55                    &config, context
56                )
57            }).collect();
58        
59        let responses = join_all(responses).await;
60        
61        let (responses, response_erros): (Vec<_>, Vec<_>) = responses.into_iter().partition(Result::is_ok);
62        
63        let mut repos_erros: Vec<Error> = response_erros.into_iter().map(Result::unwrap_err).collect();
64        let mut repos: Vec<Repo> = Vec::new();
65        
66        animation.change_message("formating repositories");
67        
68        for response in responses {
69            match self.get_repo(response) {
70                Ok(r) => repos.extend(r),
71                Err(e) => repos_erros.push(e),
72            }
73        }
74        
75        (repos, error, repos_erros)
76    }
77    
78    pub fn get_repo(&self, response: Result<String, Error>) -> Result<Vec<Repo>, Error> {
79        match response {
80            Ok(rs) => Repo::from_text_array(&rs, &self),
81            Err(_) => { unreachable!() }
82        }
83    }
84}