gitlab_time_report_cli/
fetch_projects.rs1#![cfg(not(tarpaulin_include))]
4
5use gitlab_time_report::model::Project;
6use gitlab_time_report::{FetchOptions, QueryError};
7
8pub(super) fn fetch_project(
10 url: &str,
11 token: Option<&String>,
12) -> Result<Project, Box<dyn std::error::Error>> {
13 let fetch_options = FetchOptions::new(url, token.cloned())?;
14
15 let project_result = gitlab_time_report::fetch_project_time_logs(&fetch_options);
16 match project_result {
17 Ok(project) => Ok(project),
18 Err(QueryError::ProjectNotFound(url)) => {
19 print_project_not_found(&url);
20 Err(QueryError::ProjectNotFound(url).into())
21 }
22 Err(error) => Err(error.into()),
23 }
24}
25
26pub(super) fn fetch_projects(
28 urls: Vec<String>,
29 token: Option<&String>,
30) -> Result<Project, Box<dyn std::error::Error>> {
31 let mut url_iter = urls.into_iter();
33 let first_url = url_iter.next().expect("Should be at least one URL");
34 println!("Fetching time logs from '{first_url}'...");
35 let mut project = fetch_project(&first_url, token)?;
36
37 for url in url_iter {
39 println!("Fetching time logs from '{url}'...");
40 let current_project = fetch_project(&url, token)?;
41 project.merge(current_project);
42 }
43 Ok(project)
44}
45
46fn print_project_not_found(url: &str) {
49 let (host, path) = url.split_once('/').expect("Should be a URL with one `/`");
50 eprintln!("\
51Project \"{url}\" could not be found. If the project visibility is set to 'internal' or 'private', \
52you need to provide a GitLab access token with the 'read_api' permission and \
53specify it with the --token option.
54
55You can use a personal, group or project access token. Create a new one with one of the following URLs:
56Personal: https://{host}/-/user_settings/personal_access_tokens?name=GitLab+Time-Report&scopes=read_api
57Project: https://{host}/{path}/-/settings/access_tokens
58Group: Navigate to your group settings => Access Tokens => Generate new token\n");
59}