aboutsummaryrefslogtreecommitdiff
path: root/src/local/mod.rs
diff options
context:
space:
mode:
authorMax Audron <audron@cocaine.farm>2022-06-07 12:28:18 +0200
committerMaximilian Manz <maximilian.manz@de.clara.net>2022-06-20 11:33:04 +0200
commitae13cbecdbeca984e0d389732356c2785eab66d9 (patch)
treeccd76a92e16d47d23530b87ecdf21b57e40917ef /src/local/mod.rs
parentfix crash while walking non existing dir (diff)
implement cloning of new repos
Diffstat (limited to 'src/local/mod.rs')
-rw-r--r--src/local/mod.rs72
1 files changed, 18 insertions, 54 deletions
diff --git a/src/local/mod.rs b/src/local/mod.rs
index e2f4a9d..ec8985b 100644
--- a/src/local/mod.rs
+++ b/src/local/mod.rs
@@ -1,4 +1,7 @@
-use std::{fmt::Debug, path::PathBuf};
+use std::{
+ fmt::Debug,
+ path::{Path, PathBuf},
+};
use thiserror::Error;
@@ -9,75 +12,25 @@ use crate::forge::Project;
mod aggregate;
mod repostate;
+mod sync;
mod update;
pub use aggregate::*;
pub use repostate::*;
+pub use sync::*;
pub use update::*;
pub type Repos = Vec<Repo>;
pub struct Repo {
pub name: String,
+ pub path: PathBuf,
pub repo: Option<Repository>,
pub forge: Option<Project>,
pub default_branch: String,
}
impl Repo {
- /// Fetch any new state from the remote and fast forward merge changes into local branches
- #[tracing::instrument(level = "trace")]
- pub fn update(&mut self) -> Result<UpdateResult, UpdateResult> {
- let repo_name = self.name.clone();
- if self.repo.is_some() {
- self.update_inner()
- .map_err(|e| UpdateResult::err(repo_name, e.into()))
- } else {
- Ok(UpdateResult::err(repo_name, RepoError::NoLocalRepo))
- }
- }
-
- fn update_inner(&mut self) -> Result<UpdateResult, RepoError> {
- let repo = self.repo.as_ref().unwrap();
- let mut remote = self.main_remote(repo)?;
-
- self.fetch(&mut remote)?;
-
- self.default_branch = remote.default_branch()?.as_str().unwrap().to_string();
-
- debug!("default branch: {}", self.default_branch);
-
- if self.is_clean()? {
- debug!("repo is clean");
-
- let merged = repo.branches(Some(BranchType::Local))?
- .filter_map(|x| x.ok())
- .try_fold(false, |mut merged, (mut branch, _)| {
- let name = format!("refs/heads/{}", Repo::branch_name(&branch));
-
- if branch.upstream().is_ok() {
- let upstream = branch.upstream().unwrap();
-
- debug!("branch: {}", name);
-
- merged |= self.merge(repo, &mut branch, &upstream)?;
- Ok::<bool, RepoError>(merged)
- } else {
- debug!("not updating branch: {}: branch does not have upstream tracking branch set", name);
- Ok(merged)
- }
- })?;
-
- if merged {
- Ok(UpdateResult::merged(self.name.clone()))
- } else {
- Ok(UpdateResult::no_changes(self.name.clone()))
- }
- } else {
- Ok(UpdateResult::dirty(self.name.clone()))
- }
- }
-
pub fn is_clean(&self) -> Result<bool, RepoError> {
if let Some(repo) = &self.repo {
debug!("repo state: {:?}", repo.state());
@@ -134,6 +87,15 @@ impl Repo {
Ok(())
}
+ #[tracing::instrument(level = "trace")]
+ pub fn clone(&self, url: &str) -> Result<Repository, RepoError> {
+ let mut builder = git2::build::RepoBuilder::new();
+ builder.fetch_options(crate::git::fetch_options());
+
+ builder.clone(url, &self.path).map_err(|err| RepoError::GitError(err))
+ }
+
+ #[tracing::instrument(level = "trace")]
pub fn checkout(&self) -> Result<(), RepoError> {
if let Some(repo) = &self.repo {
repo.checkout_head(None).map_err(|e| e.into())
@@ -149,6 +111,7 @@ impl Repo {
}
}
+ #[tracing::instrument(level = "trace", skip(repo, local, upstream))]
pub fn merge(
&self,
repo: &Repository,
@@ -264,6 +227,7 @@ impl Default for Repo {
fn default() -> Self {
Self {
name: Default::default(),
+ path: Default::default(),
repo: Default::default(),
forge: Default::default(),
default_branch: "main".to_string(),