aboutsummaryrefslogtreecommitdiff
path: root/src/main.rs
diff options
context:
space:
mode:
authorValentin Popov <valentin@popov.link>2024-01-12 01:07:40 +0300
committerValentin Popov <valentin@popov.link>2024-01-12 01:07:40 +0300
commit352151bd3171521c9c8441fa87e780ecff12b6ab (patch)
tree69aaed6b0fc98d685d3e4f71139976210b7a3051 /src/main.rs
parentfdd3eb83229bfe8032f87b570d24d6b91d581b31 (diff)
downloadgitlab-duplicator-352151bd3171521c9c8441fa87e780ecff12b6ab.tar.xz
gitlab-duplicator-352151bd3171521c9c8441fa87e780ecff12b6ab.zip
First version of the finished tool
Signed-off-by: Valentin Popov <valentin@popov.link>
Diffstat (limited to 'src/main.rs')
-rw-r--r--src/main.rs107
1 files changed, 75 insertions, 32 deletions
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<u64, Box<dyn Error>> {
+ 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<dyn Error>> {
+ 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);
}