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<GitlabRepository> = vec![];
let mut page = 1;
loop {
let mut values = client
.get(format!(
"https://{}/api/v4/projects?membership=true&page={}&per_page=100",
provider.host, page
))
.header("Authorization", format!("Bearer {}", &provider.token))
.send()
.with_context(|| {
format!(
"Unable to fetch {} API, please check your credentials",
provider.host
)
})?
.json::<Vec<GitlabRepository>>()
.context("Unable to deserialize repositories")?
.into_iter()
.filter(|r| !exclusions.is_match(&r.full_name()))
.collect::<Vec<GitlabRepository>>();
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 GitlabRepository {
pub id: usize,
pub name: String,
pub path_with_namespace: String,
pub visibility: String, pub default_branch: String,
pub ssh_url_to_repo: String,
pub http_url_to_repo: String,
pub web_url: String,
pub archived: bool,
pub created_at: String,
pub updated_at: String,
pub last_activity_at: String,
}
impl GenericRepository for GitlabRepository {
fn full_name(&self) -> String {
self.path_with_namespace.to_string()
}
fn default_branch(&self) -> String {
self.default_branch.to_string()
}
}