gitbackup 0.2.6

Backup all your git repositories with a single command
use crate::helpers::sync_repositories;
use crate::types::{GenericRepository, Provider};
use anyhow::{Context, Result};
use regex::RegexSetBuilder;
use reqwest::blocking;
use serde::Deserialize;
use std::path::Path;

pub fn run(backup_path: &Path, provider: &Provider) -> Result<()> {
    let exclusions = RegexSetBuilder::new(&provider.exclude)
        .case_insensitive(true)
        .build()?;

    let client = blocking::Client::new();
    let mut repositories: Vec<GithubRepository> = vec![];
    let mut page = 1;

    println!("Retrieving list of {} repositories...", provider.host);

    loop {
        let mut values = client
            .get(format!(
                "https://api.{}/user/repos?per_page=100&page={}",
                provider.host, page
            ))
            .header("Accept", "application/vnd.github+json")
            .header("User-Agent", &provider.username)
            .header("Authorization", format!("token {}", &provider.token))
            .send()
            .context("Unable to fetch Github API, please check your credentials")?
            .json::<Vec<GithubRepository>>()
            .context("Unable to deserialize repositories")?
            .into_iter()
            .filter(|r| !exclusions.is_match(&r.full_name()))
            .collect::<Vec<GithubRepository>>();

        if values.is_empty() {
            break;
        }

        repositories.append(&mut values);
        page += 1;
    }

    sync_repositories(backup_path, provider, &repositories);

    Ok(())
}

#[allow(dead_code)]
#[derive(Deserialize, Debug)]
struct GithubRepository {
    pub id: usize,
    pub name: String,
    pub full_name: String,
    pub private: bool,
    pub default_branch: String,
    pub git_url: String,
    pub ssh_url: String,
    pub clone_url: String,
    pub html_url: String,
    pub archive_url: String,
    pub archived: bool,
    pub disabled: bool,
    pub created_at: String,
    pub updated_at: String,
    pub pushed_at: String,
}

impl GenericRepository for GithubRepository {
    fn full_name(&self) -> String {
        self.full_name.to_string()
    }

    fn default_branch(&self) -> String {
        self.default_branch.to_string()
    }
}