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