From 352151bd3171521c9c8441fa87e780ecff12b6ab Mon Sep 17 00:00:00 2001 From: Valentin Popov Date: Fri, 12 Jan 2024 02:07:40 +0400 Subject: First version of the finished tool Signed-off-by: Valentin Popov --- src/main.rs | 107 ++++++++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 75 insertions(+), 32 deletions(-) (limited to 'src/main.rs') diff --git a/src/main.rs b/src/main.rs index aa2f233..1d6f34d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,18 +2,11 @@ extern crate dotenv_codegen; extern crate git2; +use std::error::Error; use std::path::Path; use clap::Parser; use git2::{Cred, RemoteCallbacks}; -use gitlab::api::{projects, Query}; -use gitlab::Gitlab; -use serde::Deserialize; - -#[derive(Debug, Deserialize)] -struct Project { - http_url_to_repo: String, -} /// Create a mirror of a repository #[derive(Parser, Debug)] @@ -26,32 +19,28 @@ struct Args { /// The URL of the repository to clone #[arg(short, long)] repo: String, - - /// The username to use for authentication - #[arg(long)] - username: String, - - /// The password to use for authentication - #[arg(long)] - password: String, } -/* Get project info from Gitlab */ -fn get_project(url: &str) -> Project { - let client = Gitlab::new(dotenv!("GITLAB_URL"), dotenv!("GITLAB_TOKEN")).unwrap(); - - let endpoint = projects::Project::builder().project(url).build().unwrap(); - let project: Project = endpoint.query(&client).unwrap(); +fn get_project_url(repo: &str) -> String { + format!("https://{}/{}.git", dotenv!("GITLAB_URL"), repo) +} - project +fn get_remote_url(repo: &str) -> String { + format!( + "https://{}:{}@{}/{}", + dotenv!("REMOTE_USERNAME"), + dotenv!("REMOTE_PASSWORD"), + dotenv!("REMOTE_URL"), + repo + ) } /* Clone project from Gitlab */ -fn clone_project(repo: &str, path: &str, username: &str, password: &str) { +fn clone_remote_project(repo: &str, path: &str) { // Callbacks for authentication let mut cb = RemoteCallbacks::new(); cb.credentials(|_url, _username_from_url, _allowed_types| { - Cred::userpass_plaintext(username, password) + Cred::userpass_plaintext(dotenv!("GITLAB_USERNAME"), dotenv!("GITLAB_PASSWORD")) }); // Prepare fetch options @@ -69,16 +58,70 @@ fn clone_project(repo: &str, path: &str, username: &str, password: &str) { builder.clone(repo, Path::new(&path)).unwrap(); } +/* Get project ID from Gitlab */ +fn get_project_id(project_name: &str) -> Result> { + let client = reqwest::blocking::Client::new(); + let encoded_name = urlencoding::encode(project_name); + + let api_url = format!( + "https://{}/api/v4/projects/{}", + dotenv!("GITLAB_URL"), + encoded_name + ); + + let response = client + .get(&api_url) + .bearer_auth(dotenv!("GITLAB_TOKEN")) + .send()?; + + if response.status().is_success() { + let project_info: serde_json::Value = response.json()?; + Ok(project_info["id"].as_u64().unwrap()) + } else { + Err("Failed to get project ID".into()) + } +} + +/* Add mirror to Gitlab */ +fn add_gitlab_mirror(repo_id: u64, mirror_url: &str) -> Result<(), Box> { + let client = reqwest::blocking::Client::new(); + + let api_url = format!( + "https://{}/api/v4/projects/{}/remote_mirrors", + dotenv!("GITLAB_URL"), + repo_id + ); + + let response = client + .post(&api_url) + .bearer_auth(dotenv!("GITLAB_TOKEN")) + .json(&serde_json::json!({ + "url": mirror_url, + "enabled": true, + "keep_divergent_refs": false, + "only_protected_branches": false, + })) + .send()?; + + dbg!(response.status()); + if response.status().is_success() { + Ok(()) + } else { + Err("Failed to add mirror".into()) + } +} + fn main() { dotenv::dotenv().ok(); let args = Args::parse(); - let project = get_project(&args.repo); - clone_project( - &project.http_url_to_repo, - &args.path, - &args.username, - &args.password, - ); + let project_id = get_project_id(&args.repo).unwrap(); + let mirror_url = get_remote_url(&args.path); + add_gitlab_mirror(project_id, &mirror_url).unwrap(); + + dbg!(&project_id); + dbg!(&mirror_url); + + clone_remote_project(&get_project_url(&args.repo), &args.path); } -- cgit v1.2.3