diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/database.rs | 24 | ||||
-rw-r--r-- | src/git.rs | 124 | ||||
-rw-r--r-- | src/github.rs | 4 | ||||
-rw-r--r-- | src/main.rs | 4 |
4 files changed, 134 insertions, 22 deletions
diff --git a/src/database.rs b/src/database.rs index ed5d327..09fedd7 100644 --- a/src/database.rs +++ b/src/database.rs @@ -1,4 +1,4 @@ -// Copyright (c) 2021 Teddy Wing +// Copyright (c) 2021, 2022 Teddy Wing // // This file is part of Reflectub. // @@ -44,12 +44,32 @@ impl Repo { impl From<&github::Repo> for Repo { fn from(repo: &github::Repo) -> Self { + use chrono::DateTime; + + let repo_updated_at = DateTime::parse_from_rfc3339(&repo.updated_at).ok(); + let repo_pushed_at = DateTime::parse_from_rfc3339(&repo.pushed_at).ok(); + + // Set `updated_at` to the most recent of `repo_updated_at` or + // `repo_pushed_at`. + let updated_at = + if repo_updated_at.is_none() && repo_pushed_at.is_none() { + repo.updated_at.clone() + + // `repo_updated_at` and `repo_pushed_at` are both Some. + } else if repo_pushed_at.unwrap() > repo_updated_at.unwrap() { + repo.pushed_at.clone() + + // Default to `repo.updated_at`. + } else { + repo.updated_at.clone() + }; + Self { id: repo.id, name: Some(repo.name.clone()), description: repo.description.clone(), default_branch: Some(repo.default_branch.clone()), - updated_at: Some(repo.updated_at.clone()), + updated_at: Some(updated_at), } } } @@ -1,4 +1,4 @@ -// Copyright (c) 2021 Teddy Wing +// Copyright (c) 2021, 2022 Teddy Wing // // This file is part of Reflectub. // @@ -25,6 +25,58 @@ use std::path::Path; #[derive(Debug, thiserror::Error)] pub enum Error { + #[error("mirror: cannot create repo '{path}'")] + MirrorCreateRepo { + source: git2::Error, + path: String, + }, + #[error("mirror: cannot add remote '{remote_name}:{url}'")] + MirrorAddRemote { + source: git2::Error, + remote_name: String, + url: String, + }, + #[error("mirror: cannot get repo config")] + MirrorConfigGet(#[source] git2::Error), + #[error("mirror: cannot set 'mirror' flag on remote '{remote_name}'")] + MirrorRemoteEnableMirror { + source: git2::Error, + remote_name: String, + }, + #[error("mirror: cannot fetch from remote '{remote_name}'")] + MirrorFetch { + source: git2::Error, + remote_name: String, + }, + + #[error("update: cannot open repo '{path}'")] + UpdateOpenRepo { + source: git2::Error, + path: String, + }, + #[error("update: cannot get remotes for '{path}'")] + UpdateGetRemotes { + source: git2::Error, + path: String, + }, + #[error("update: cannot find remote '{remote_name}'")] + UpdateFindRemote { + source: git2::Error, + remote_name: String, + }, + #[error("update: cannot fetch from remote '{remote_name}")] + UpdateFetch { + source: git2::Error, + remote_name: String, + }, + + #[error("{action}: cannot switch to branch '{branch}'")] + GitChangeBranch { + source: git2::Error, + action: String, + branch: String, + }, + #[error("git error")] Git(#[from] git2::Error), @@ -40,7 +92,7 @@ pub enum Error { /// ```shell /// git clone --mirror URL /// ``` -pub fn mirror<P: AsRef<Path>>( +pub fn mirror<P: AsRef<Path> + Copy>( url: &str, path: P, description: &str, @@ -56,7 +108,11 @@ pub fn mirror<P: AsRef<Path>>( // Mac OS. .external_template(false) .description(description), - )?; + ) + .map_err(|e| Error::MirrorCreateRepo { + source: e, + path: format!("{}", path.as_ref().display()), + })?; let remote_name = "origin"; @@ -64,19 +120,38 @@ pub fn mirror<P: AsRef<Path>>( remote_name, url, "+refs/*:refs/*", - )?; - - let mut config = repo.config()?; + ) + .map_err(|e| Error::MirrorAddRemote { + source: e, + remote_name: remote_name.to_owned(), + url: url.to_owned(), + })?; + + let mut config = repo.config() + .map_err(|e| Error::MirrorConfigGet(e))?; config.set_bool( &format!("remote.{}.mirror", remote_name), true, - )?; + ) + .map_err(|e| Error::MirrorRemoteEnableMirror { + source: e, + remote_name: remote_name.to_owned(), + })?; let refspecs: [&str; 0] = []; - remote.fetch(&refspecs, None, None)?; + remote.fetch(&refspecs, None, None) + .map_err(|e| Error::MirrorFetch { + source: e, + remote_name: remote_name.to_owned(), + })?; if default_branch != "master" { - repo_change_current_branch(&repo, default_branch)?; + repo_change_current_branch(&repo, default_branch) + .map_err(|e| Error::GitChangeBranch { + source: e, + action: "mirror".to_owned(), + branch: default_branch.to_owned(), + })?; } Ok(()) @@ -89,14 +164,27 @@ pub fn mirror<P: AsRef<Path>>( /// ```shell /// git remote update /// ``` -pub fn update<P: AsRef<Path>>( +pub fn update<P: AsRef<Path> + Copy>( path: P, ) -> Result<(), Error> { - let repo = git2::Repository::open_bare(path)?; - - for remote_opt in &repo.remotes()? { + let repo = git2::Repository::open_bare(path) + .map_err(|e| Error::UpdateOpenRepo { + source: e, + path: format!("{}", path.as_ref().display()), + })?; + + let remotes = &repo.remotes() + .map_err(|e| Error::UpdateGetRemotes { + source: e, + path: format!("{}", path.as_ref().display()), + })?; + for remote_opt in remotes { if let Some(remote_name) = remote_opt { - let mut remote = repo.find_remote(remote_name)?; + let mut remote = repo.find_remote(remote_name) + .map_err(|e| Error::UpdateFindRemote { + source: e, + remote_name: remote_name.to_owned(), + })?; let mut fetch_options = git2::FetchOptions::new(); fetch_options @@ -104,7 +192,11 @@ pub fn update<P: AsRef<Path>>( .download_tags(git2::AutotagOption::All); let refspecs: [&str; 0] = []; - remote.fetch(&refspecs, Some(&mut fetch_options), None)?; + remote.fetch(&refspecs, Some(&mut fetch_options), None) + .map_err(|e| Error::UpdateFetch { + source: e, + remote_name: remote_name.to_owned(), + })?; } } @@ -149,7 +241,7 @@ pub fn change_current_branch<P: AsRef<Path>>( fn repo_change_current_branch( repo: &git2::Repository, default_branch: &str, -) -> Result<(), Error> { +) -> Result<(), git2::Error> { Ok( repo.set_head( &format!("refs/heads/{}", default_branch), diff --git a/src/github.rs b/src/github.rs index a3bb74e..c48dda6 100644 --- a/src/github.rs +++ b/src/github.rs @@ -1,4 +1,4 @@ -// Copyright (c) 2021 Teddy Wing +// Copyright (c) 2021, 2022 Teddy Wing // // This file is part of Reflectub. // @@ -43,7 +43,7 @@ pub struct Repo { pub name: String, pub description: Option<String>, pub fork: bool, - pub git_url: String, + pub clone_url: String, pub default_branch: String, pub size: u64, pub updated_at: String, diff --git a/src/main.rs b/src/main.rs index 6ff441b..61996e8 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,4 @@ -// Copyright (c) 2021 Teddy Wing +// Copyright (c) 2021, 2022 Teddy Wing // // This file is part of Reflectub. // @@ -241,7 +241,7 @@ where P2: AsRef<Path>, { git::mirror( - &repo.git_url, + &repo.clone_url, &clone_path, repo.description(), &repo.default_branch, |