repo_backup/
github.rs

1use failure::{Error, ResultExt};
2use std::fmt::{self, Debug, Formatter};
3
4use config::GithubConfig;
5use utils::Paginated;
6use {Provider, Repo};
7
8/// An interface to the repositories stored on github.
9#[derive(Clone)]
10pub struct GitHub {
11    cfg: GithubConfig,
12}
13
14impl GitHub {
15    /// Create a new `GitHub` with the provided config.
16    pub fn with_config(cfg: GithubConfig) -> GitHub {
17        GitHub { cfg }
18    }
19
20    fn get_owned(&self) -> Result<Vec<Repo>, Error> {
21        debug!("Fetching owned repositories");
22
23        let mut owned = Vec::new();
24
25        for repo in Paginated::new(
26            self.cfg.api_key.reveal_str(),
27            "https://api.github.com/user/repos",
28        ) {
29            let repo: RawRepo = repo?;
30            owned.push(self.convert_repo(repo));
31        }
32
33        debug!("{} owned repos", owned.len());
34        Ok(owned)
35    }
36
37    fn get_starred(&self) -> Result<Vec<Repo>, Error> {
38        debug!("Fetching starred repositories");
39
40        let mut starred = Vec::new();
41
42        for repo in Paginated::new(
43            self.cfg.api_key.reveal_str(),
44            "https://api.github.com/user/starred",
45        ) {
46            let repo: RawRepo = repo?;
47            starred.push(self.convert_repo(repo));
48        }
49
50        debug!("{} starred repos", starred.len());
51        Ok(starred)
52    }
53
54    fn convert_repo(&self, raw: RawRepo) -> Repo {
55        Repo {
56            name: raw.name,
57            owner: raw.owner.login,
58            url: raw.clone_url,
59            provider: self.name().to_string(),
60        }
61    }
62}
63
64impl Provider for GitHub {
65    fn name(&self) -> &str {
66        "github"
67    }
68
69    fn repositories(&self) -> Result<Vec<Repo>, Error> {
70        let mut repos = Vec::new();
71
72        if self.cfg.owned {
73            repos.extend(
74                self.get_owned()
75                    .context("Unable to fetch owned repositories")?,
76            );
77        }
78        if self.cfg.starred {
79            repos.extend(
80                self.get_starred()
81                    .context("Unable to fetch starred repositories")?,
82            );
83        }
84
85        Ok(repos)
86    }
87}
88
89impl Debug for GitHub {
90    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
91        f.debug_struct("GitHub").finish()
92    }
93}
94
95#[derive(Debug, Clone, Default, Deserialize)]
96#[serde(default)]
97struct RawRepo {
98    name: String,
99    clone_url: String,
100    owner: Owner,
101}
102
103#[derive(Debug, Clone, Default, Deserialize)]
104#[serde(default)]
105struct Owner {
106    login: String,
107    #[serde(rename = "type")]
108    kind: String,
109}