repo_backup/
gitlab_provider.rs1use failure::{Error, ResultExt};
2use gitlab::{Gitlab as Client, Project};
3
4use config::GitLabConfig;
5use {Provider, Repo, SyncResult};
6
7#[derive(Debug)]
9pub struct GitLab {
10 client: Client,
11 cfg: GitLabConfig,
12}
13
14impl GitLab {
15 pub fn with_config(cfg: GitLabConfig) -> Result<GitLab, Error> {
17 let client = Client::new(&cfg.host, cfg.api_key.reveal_str())
18 .sync()
19 .context("Invalid API key")?;
20
21 Ok(GitLab { client, cfg })
22 }
23
24 fn get_owned(&self) -> Result<Vec<Repo>, Error> {
25 debug!("Fetching owned repos");
26 let owned = self.client.owned_projects().sync()?;
27
28 let repos: Vec<Repo> = owned
29 .into_iter()
30 .map(|p| self.gitlab_project_to_repo(p))
31 .collect();
32
33 debug!("Found {} owned projects", repos.len());
34
35 Ok(repos)
36 }
37
38 fn get_organisation_repos(&self) -> Result<Vec<Repo>, Error> {
39 debug!("Fetching organisation repos");
40
41 let current_user = self
42 .client
43 .current_user()
44 .sync()
45 .context("Unable to get the name of the current user")?
46 .username;
47 trace!("Current GitLab user is {}", current_user);
48
49 let all_repos = self.client.projects().sync()?;
50
51 let org_repos: Vec<Repo> = all_repos
52 .into_iter()
53 .map(|p| self.gitlab_project_to_repo(p))
54 .filter(|r| r.owner != current_user)
55 .collect();
56
57 debug!(
58 "Found {} repos owned by organisations you are a part of",
59 org_repos.len()
60 );
61 Ok(org_repos)
62 }
63
64 fn gitlab_project_to_repo(&self, project: Project) -> Repo {
65 let mut split = project.path_with_namespace.split("/");
66 let owner = split.next().expect("Namespaces always have an owner");
67 let name = split.next().expect("unreachable");
68
69 Repo {
70 owner: owner.to_string(),
71 name: name.to_string(),
72 url: project.ssh_url_to_repo,
73 provider: self.name().to_string(),
74 }
75 }
76}
77
78impl Provider for GitLab {
79 fn name(&self) -> &str {
80 "gitlab"
81 }
82
83 fn repositories(&self) -> Result<Vec<Repo>, Error> {
84 let mut repos = Vec::new();
85
86 if self.cfg.owned {
87 let owned =
88 self.get_owned().context("Unable to get owned repos")?;
89 repos.extend(owned);
90 }
91
92 if self.cfg.organisations {
93 let org_repos = self.get_organisation_repos().context(
94 "Unable to get repos owned by organisations you are a part of",
95 )?;
96 repos.extend(org_repos);
97 }
98
99 Ok(repos)
100 }
101}