Skip to content

Commit 357c868

Browse files
committed
implement mirroring
1 parent 8138a4c commit 357c868

File tree

1 file changed

+85
-5
lines changed

1 file changed

+85
-5
lines changed

src/main.rs

+85-5
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use serde_derive::Deserialize;
1+
use serde_derive::{Deserialize, Serialize};
22
use std::path::PathBuf;
33
mod config;
44

@@ -89,20 +89,100 @@ fn collect_github_repos(config: &config::Config) -> Vec<Repo> {
8989
} else {
9090
"/user/repos?visibility=public"
9191
};
92-
let mut repos = get_repos(&config, &endpoint.to_string(), RepoType::GitHub);
92+
let mut repos = get_repos(config, &endpoint.to_string(), RepoType::GitHub);
9393

9494
if config.github.include_starred {
95-
let mut starred = get_repos(&config, &"/user/starred".to_string(), RepoType::GitHub);
95+
let mut starred = get_repos(config, &"/user/starred".to_string(), RepoType::GitHub);
9696
repos.append(&mut starred);
9797
}
9898

9999
repos
100100
}
101101

102+
#[derive(Serialize)]
103+
struct MigrateRepoOptions {
104+
auth_token: String,
105+
clone_addr: String,
106+
description: String,
107+
issues: bool,
108+
lfs: bool,
109+
mirror: bool,
110+
mirror_interval: String,
111+
private: bool,
112+
pull_requests: bool,
113+
releases: bool,
114+
repo_name: String,
115+
repo_owner: String,
116+
wiki: bool,
117+
}
118+
119+
fn mirror_repo(repo: &Repo, config: &config::Config) {
120+
let mut payload = MigrateRepoOptions {
121+
auth_token: config.github.token.clone(),
122+
clone_addr: repo.clone_url.clone(),
123+
description: format!("Mirror of {}", repo.clone_url),
124+
issues: true,
125+
lfs: true,
126+
mirror: true,
127+
mirror_interval: "2h".to_string(),
128+
private: true,
129+
pull_requests: true,
130+
releases: true,
131+
repo_name: repo.name.clone(),
132+
repo_owner: config.gitea.user.clone(),
133+
wiki: true,
134+
};
135+
if !config.gitea.keep_private {
136+
payload.private = repo.private;
137+
}
138+
139+
// prefix repo name with owner name if owner is not the github user
140+
if repo.owner.login != config.github.user {
141+
payload.repo_name = format!("{}_{}", repo.owner.login, repo.name);
142+
}
143+
144+
println!(
145+
"Mirroring {} to {}/{}",
146+
repo.full_name, payload.repo_owner, payload.repo_name
147+
);
148+
149+
let payload = serde_json::to_string(&payload).unwrap();
150+
let endpoint = format!("{}/api/v1/repos/migrate", config.gitea.url);
151+
152+
let mut buffer: Vec<u8> = Vec::new();
153+
match http_req::request::Request::new(&endpoint.as_str().try_into().unwrap())
154+
.method(http_req::request::Method::POST)
155+
.body(payload.as_bytes())
156+
.header("User-Agent", "teahub")
157+
.header("Content-Length", &payload.len())
158+
.header("Content-Type", "application/json")
159+
.header("Authorization", &format!("token {}", &config.gitea.token))
160+
.send(&mut buffer)
161+
{
162+
Ok(req) => {
163+
if req.status_code() == http_req::response::StatusCode::new(409) {
164+
println!("{} already exists", repo.name);
165+
} else if req.status_code() != http_req::response::StatusCode::new(201) {
166+
panic!("Error: {:?}", req);
167+
}
168+
}
169+
Err(error) => panic!("Error: {:?}", error),
170+
}
171+
}
172+
102173
fn main() {
103174
let config = config::load_config(PathBuf::from("config.toml"));
104175
let github_repos = collect_github_repos(&config);
105-
println!("GH repos: {:?}", github_repos.len());
106176
let gitea_repos = get_repos(&config, &"/user/repos".to_string(), RepoType::Gitea);
107-
println!("GT repos: {:?}", gitea_repos.len());
177+
178+
let gitea_repos_names: Vec<String> = gitea_repos.iter().map(|r| r.name.clone()).collect();
179+
for repo in github_repos {
180+
let prefixed_name = format!("{}_{}", repo.owner.login, repo.name);
181+
if gitea_repos_names.contains(&repo.name) || gitea_repos_names.contains(&prefixed_name) {
182+
println!("{} already exists", repo.name);
183+
continue;
184+
}
185+
186+
mirror_repo(&repo, &config);
187+
}
108188
}

0 commit comments

Comments
 (0)