diff options
Diffstat (limited to 'src/local/update.rs')
| -rw-r--r-- | src/local/update.rs | 71 |
1 files changed, 67 insertions, 4 deletions
diff --git a/src/local/update.rs b/src/local/update.rs index 95057a4..d9c9f3c 100644 --- a/src/local/update.rs +++ b/src/local/update.rs @@ -1,4 +1,64 @@ -use std::fmt::Display; +use std::fmt::{Debug, Display}; + +use git2::BranchType; +use tracing::debug; + +use super::{Repo, RepoError}; + +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())) + } + } +} #[derive(Debug)] pub enum UpdateResult { @@ -49,9 +109,12 @@ impl Display for UpdateResult { UpdateResult::Merged { name } => { f.write_fmt(format_args!("{} {}", Green.paint("PULLED "), name)) } - UpdateResult::Error { name, error } => { - f.write_fmt(format_args!("{} {} [{}]", Red.paint("ERROR "), name, error)) - } + UpdateResult::Error { name, error } => f.write_fmt(format_args!( + "{} {} [{}]", + Red.paint("ERROR "), + name, + error + )), } } } |
