forked from kemitix/git-next
refactor: reimplement git fetch using git
This commit is contained in:
parent
313d6d79c5
commit
6c60e3fb7a
17 changed files with 53 additions and 53 deletions
|
@ -19,7 +19,7 @@ use tracing::{info, instrument, warn};
|
||||||
pub fn advance_next(
|
pub fn advance_next(
|
||||||
commit: Option<Commit>,
|
commit: Option<Commit>,
|
||||||
force: git_next_core::git::push::Force,
|
force: git_next_core::git::push::Force,
|
||||||
repo_details: RepoDetails,
|
repo_details: &RepoDetails,
|
||||||
repo_config: RepoConfig,
|
repo_config: RepoConfig,
|
||||||
open_repository: &dyn OpenRepositoryLike,
|
open_repository: &dyn OpenRepositoryLike,
|
||||||
message_token: MessageToken,
|
message_token: MessageToken,
|
||||||
|
@ -29,7 +29,7 @@ pub fn advance_next(
|
||||||
info!("Advancing next to commit '{}'", commit);
|
info!("Advancing next to commit '{}'", commit);
|
||||||
reset(
|
reset(
|
||||||
open_repository,
|
open_repository,
|
||||||
&repo_details,
|
repo_details,
|
||||||
&repo_config.branches().next(),
|
&repo_config.branches().next(),
|
||||||
&commit.into(),
|
&commit.into(),
|
||||||
&force,
|
&force,
|
||||||
|
|
|
@ -41,7 +41,7 @@ impl Handler<AdvanceMain> for RepoActor {
|
||||||
} else {
|
} else {
|
||||||
self.update_tui(RepoUpdate::MainUpdated);
|
self.update_tui(RepoUpdate::MainUpdated);
|
||||||
if let Some(open_repository) = &self.open_repository {
|
if let Some(open_repository) = &self.open_repository {
|
||||||
match open_repository.fetch() {
|
match open_repository.fetch(&repo_details) {
|
||||||
Ok(()) => self.update_tui_log(git::graph::log(&self.repo_details)),
|
Ok(()) => self.update_tui_log(git::graph::log(&self.repo_details)),
|
||||||
Err(err) => self.alert_tui(format!("fetching: {err}")),
|
Err(err) => self.alert_tui(format!("fetching: {err}")),
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,14 +44,14 @@ impl Handler<AdvanceNext> for RepoActor {
|
||||||
match advance_next(
|
match advance_next(
|
||||||
commit,
|
commit,
|
||||||
force,
|
force,
|
||||||
repo_details,
|
&repo_details,
|
||||||
repo_config,
|
repo_config,
|
||||||
&**open_repository,
|
&**open_repository,
|
||||||
self.message_token,
|
self.message_token,
|
||||||
) {
|
) {
|
||||||
Ok(message_token) => {
|
Ok(message_token) => {
|
||||||
self.update_tui(RepoUpdate::NextUpdated);
|
self.update_tui(RepoUpdate::NextUpdated);
|
||||||
match open_repository.fetch() {
|
match open_repository.fetch(&repo_details) {
|
||||||
Ok(()) => self.update_tui_log(git::graph::log(&self.repo_details)),
|
Ok(()) => self.update_tui_log(git::graph::log(&self.repo_details)),
|
||||||
Err(err) => self.alert_tui(format!("fetching: {err}")),
|
Err(err) => self.alert_tui(format!("fetching: {err}")),
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ fn advance_next_sut(
|
||||||
next: &Commit,
|
next: &Commit,
|
||||||
main: &Commit,
|
main: &Commit,
|
||||||
dev_commit_history: &[Commit],
|
dev_commit_history: &[Commit],
|
||||||
repo_details: RepoDetails,
|
repo_details: &RepoDetails,
|
||||||
repo_config: RepoConfig,
|
repo_config: RepoConfig,
|
||||||
open_repository: &dyn OpenRepositoryLike,
|
open_repository: &dyn OpenRepositoryLike,
|
||||||
message_token: MessageToken,
|
message_token: MessageToken,
|
||||||
|
@ -42,7 +42,7 @@ mod when_at_dev {
|
||||||
&next,
|
&next,
|
||||||
main,
|
main,
|
||||||
dev_commit_history,
|
dev_commit_history,
|
||||||
repo_details,
|
&repo_details,
|
||||||
repo_config,
|
repo_config,
|
||||||
&open_repository,
|
&open_repository,
|
||||||
message_token,
|
message_token,
|
||||||
|
@ -77,7 +77,7 @@ mod can_advance {
|
||||||
&next,
|
&next,
|
||||||
main,
|
main,
|
||||||
dev_commit_history,
|
dev_commit_history,
|
||||||
repo_details,
|
&repo_details,
|
||||||
repo_config,
|
repo_config,
|
||||||
&open_repository,
|
&open_repository,
|
||||||
message_token,
|
message_token,
|
||||||
|
@ -108,7 +108,7 @@ mod can_advance {
|
||||||
&next,
|
&next,
|
||||||
main,
|
main,
|
||||||
dev_commit_history,
|
dev_commit_history,
|
||||||
repo_details,
|
&repo_details,
|
||||||
repo_config,
|
repo_config,
|
||||||
&open_repository,
|
&open_repository,
|
||||||
message_token,
|
message_token,
|
||||||
|
@ -148,7 +148,7 @@ mod can_advance {
|
||||||
&next,
|
&next,
|
||||||
main,
|
main,
|
||||||
dev_commit_history,
|
dev_commit_history,
|
||||||
repo_details,
|
&repo_details,
|
||||||
repo_config,
|
repo_config,
|
||||||
&open_repository,
|
&open_repository,
|
||||||
message_token,
|
message_token,
|
||||||
|
@ -180,7 +180,7 @@ mod can_advance {
|
||||||
&next,
|
&next,
|
||||||
main,
|
main,
|
||||||
dev_commit_history,
|
dev_commit_history,
|
||||||
repo_details,
|
&repo_details,
|
||||||
repo_config,
|
repo_config,
|
||||||
&open_repository,
|
&open_repository,
|
||||||
message_token,
|
message_token,
|
||||||
|
|
|
@ -11,7 +11,7 @@ pub fn fetch(open_repository: &mut MockOpenRepositoryLike, result: Result<(), fe
|
||||||
open_repository
|
open_repository
|
||||||
.expect_fetch()
|
.expect_fetch()
|
||||||
.times(1)
|
.times(1)
|
||||||
.return_once(|| result);
|
.return_once(|_| result);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn push_ok(open_repository: &mut MockOpenRepositoryLike) {
|
pub fn push_ok(open_repository: &mut MockOpenRepositoryLike) {
|
||||||
|
|
|
@ -19,7 +19,7 @@ async fn when_repo_config_should_fetch_then_push_then_revalidate() -> TestResult
|
||||||
.expect_fetch()
|
.expect_fetch()
|
||||||
.times(1)
|
.times(1)
|
||||||
.in_sequence(&mut seq)
|
.in_sequence(&mut seq)
|
||||||
.return_once(|| Ok(()));
|
.return_once(|_| Ok(()));
|
||||||
open_repository
|
open_repository
|
||||||
.expect_push()
|
.expect_push()
|
||||||
.times(1)
|
.times(1)
|
||||||
|
@ -29,7 +29,7 @@ async fn when_repo_config_should_fetch_then_push_then_revalidate() -> TestResult
|
||||||
.expect_fetch()
|
.expect_fetch()
|
||||||
.times(1)
|
.times(1)
|
||||||
.in_sequence(&mut seq)
|
.in_sequence(&mut seq)
|
||||||
.return_once(|| Ok(()));
|
.return_once(|_| Ok(()));
|
||||||
|
|
||||||
//when
|
//when
|
||||||
let (addr, log) = when::start_actor_with_open_repository(
|
let (addr, log) = when::start_actor_with_open_repository(
|
||||||
|
@ -69,7 +69,7 @@ async fn when_app_config_should_fetch_then_push_then_revalidate() -> TestResult
|
||||||
.expect_fetch()
|
.expect_fetch()
|
||||||
.times(1)
|
.times(1)
|
||||||
.in_sequence(&mut seq)
|
.in_sequence(&mut seq)
|
||||||
.return_once(|| Ok(()));
|
.return_once(|_| Ok(()));
|
||||||
open_repository
|
open_repository
|
||||||
.expect_push()
|
.expect_push()
|
||||||
.times(1)
|
.times(1)
|
||||||
|
@ -79,7 +79,7 @@ async fn when_app_config_should_fetch_then_push_then_revalidate() -> TestResult
|
||||||
.expect_fetch()
|
.expect_fetch()
|
||||||
.times(1)
|
.times(1)
|
||||||
.in_sequence(&mut seq)
|
.in_sequence(&mut seq)
|
||||||
.return_once(|| Ok(()));
|
.return_once(|_| Ok(()));
|
||||||
|
|
||||||
//when
|
//when
|
||||||
let (addr, log) = when::start_actor_with_open_repository(
|
let (addr, log) = when::start_actor_with_open_repository(
|
||||||
|
|
|
@ -22,7 +22,7 @@ async fn should_fetch_then_push_then_revalidate() -> TestResult {
|
||||||
.expect_fetch()
|
.expect_fetch()
|
||||||
.times(1)
|
.times(1)
|
||||||
.in_sequence(&mut seq)
|
.in_sequence(&mut seq)
|
||||||
.return_once(|| Ok(()));
|
.return_once(|_| Ok(()));
|
||||||
open_repository
|
open_repository
|
||||||
.expect_push()
|
.expect_push()
|
||||||
.times(1)
|
.times(1)
|
||||||
|
@ -32,7 +32,7 @@ async fn should_fetch_then_push_then_revalidate() -> TestResult {
|
||||||
.expect_fetch()
|
.expect_fetch()
|
||||||
.times(1)
|
.times(1)
|
||||||
.in_sequence(&mut seq)
|
.in_sequence(&mut seq)
|
||||||
.return_once(|| Ok(()));
|
.return_once(|_| Ok(()));
|
||||||
|
|
||||||
//when
|
//when
|
||||||
let (addr, log) = when::start_actor_with_open_repository(
|
let (addr, log) = when::start_actor_with_open_repository(
|
||||||
|
|
|
@ -486,7 +486,7 @@ async fn should_send_validate_repo_when_retryable_error() -> TestResult {
|
||||||
//given
|
//given
|
||||||
let fs = given::a_filesystem();
|
let fs = given::a_filesystem();
|
||||||
let (mut open_repository, repo_details) = given::an_open_repository(&fs);
|
let (mut open_repository, repo_details) = given::an_open_repository(&fs);
|
||||||
open_repository.expect_fetch().return_once(|| Ok(()));
|
open_repository.expect_fetch().return_once(|_| Ok(()));
|
||||||
open_repository
|
open_repository
|
||||||
.expect_commit_log()
|
.expect_commit_log()
|
||||||
.return_once(|_, _| Err(git::commit::log::Error::Lock));
|
.return_once(|_, _| Err(git::commit::log::Error::Lock));
|
||||||
|
@ -517,7 +517,7 @@ async fn should_send_notify_user_when_non_retryable_error() -> TestResult {
|
||||||
let (mut open_repository, repo_details) = given::an_open_repository(&fs);
|
let (mut open_repository, repo_details) = given::an_open_repository(&fs);
|
||||||
#[allow(clippy::unwrap_used)]
|
#[allow(clippy::unwrap_used)]
|
||||||
let repo_config = repo_details.repo_config.clone().unwrap();
|
let repo_config = repo_details.repo_config.clone().unwrap();
|
||||||
open_repository.expect_fetch().return_once(|| Ok(()));
|
open_repository.expect_fetch().return_once(|_| Ok(()));
|
||||||
|
|
||||||
// branches are all unrelated - non-retryable until each branch is updated
|
// branches are all unrelated - non-retryable until each branch is updated
|
||||||
let branches = repo_config.branches();
|
let branches = repo_config.branches();
|
||||||
|
|
|
@ -3,6 +3,9 @@ pub type Result<T> = core::result::Result<T, Error>;
|
||||||
|
|
||||||
#[derive(Debug, thiserror::Error)]
|
#[derive(Debug, thiserror::Error)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
|
#[error("io")]
|
||||||
|
Io(#[from] std::io::Error),
|
||||||
|
|
||||||
#[error("unable to open repo: {0}")]
|
#[error("unable to open repo: {0}")]
|
||||||
UnableToOpenRepo(String),
|
UnableToOpenRepo(String),
|
||||||
|
|
||||||
|
|
|
@ -61,6 +61,6 @@ pub fn reset(
|
||||||
to_commit: &git::GitRef,
|
to_commit: &git::GitRef,
|
||||||
force: &git::push::Force,
|
force: &git::push::Force,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
open_repository.fetch()?;
|
open_repository.fetch(repo_details)?;
|
||||||
open_repository.push(repo_details, branch_name, to_commit, force)
|
open_repository.push(repo_details, branch_name, to_commit, force)
|
||||||
}
|
}
|
||||||
|
|
|
@ -82,7 +82,7 @@ pub trait OpenRepositoryLike: std::fmt::Debug + Sync {
|
||||||
///
|
///
|
||||||
/// Will return an `Err` if their is no remote fetch defined in .git/config, or
|
/// Will return an `Err` if their is no remote fetch defined in .git/config, or
|
||||||
/// if there are any network connectivity issues with the remote server.
|
/// if there are any network connectivity issues with the remote server.
|
||||||
fn fetch(&self) -> Result<(), git::fetch::Error>;
|
fn fetch(&self, repo_details: &git::RepoDetails) -> Result<(), git::fetch::Error>;
|
||||||
|
|
||||||
/// Performs a `git push`
|
/// Performs a `git push`
|
||||||
///
|
///
|
||||||
|
|
|
@ -66,35 +66,32 @@ impl super::OpenRepositoryLike for RealOpenRepository {
|
||||||
|
|
||||||
#[tracing::instrument(skip_all)]
|
#[tracing::instrument(skip_all)]
|
||||||
#[cfg(not(tarpaulin_include))] // would require writing to external service
|
#[cfg(not(tarpaulin_include))] // would require writing to external service
|
||||||
fn fetch(&self) -> Result<(), git::fetch::Error> {
|
fn fetch(&self, repo_details: &git::RepoDetails) -> Result<(), git::fetch::Error> {
|
||||||
use std::sync::atomic::AtomicBool;
|
use secrecy::ExposeSecret;
|
||||||
|
|
||||||
let Ok(repository) = self.inner.read() else {
|
let origin = repo_details.origin();
|
||||||
#[cfg(not(tarpaulin_include))] // don't test mutex lock failure
|
let command: secrecy::Secret<String> =
|
||||||
return Err(git::fetch::Error::Lock);
|
format!("/usr/bin/git fetch {}", origin.expose_secret()).into();
|
||||||
|
let git_dir = self
|
||||||
|
.inner
|
||||||
|
.read()
|
||||||
|
.map_err(|_| git::fetch::Error::Lock)
|
||||||
|
.map(|r| r.git_dir().to_path_buf())?;
|
||||||
|
let ctx = gix::diff::command::Context {
|
||||||
|
git_dir: Some(git_dir),
|
||||||
|
..Default::default()
|
||||||
};
|
};
|
||||||
let thread_local = repository.to_thread_local();
|
gix::command::prepare(command.expose_secret())
|
||||||
let Some(Ok(remote)) =
|
.with_context(ctx)
|
||||||
thread_local.find_default_remote(git::repository::Direction::Fetch.into())
|
.with_shell_allow_argument_splitting()
|
||||||
else {
|
.stdout(std::process::Stdio::null())
|
||||||
#[cfg(not(tarpaulin_include))] // test is on local repo - should always have remotes
|
.stderr(std::process::Stdio::null())
|
||||||
return Err(git::fetch::Error::NoFetchRemoteFound);
|
.spawn()?
|
||||||
};
|
.wait()?;
|
||||||
remote
|
|
||||||
.connect(gix::remote::Direction::Fetch)
|
|
||||||
.map_err(|gix| git::fetch::Error::Connect(gix.to_string()))?
|
|
||||||
.prepare_fetch(
|
|
||||||
gix::progress::Discard,
|
|
||||||
gix::remote::ref_map::Options::default(),
|
|
||||||
)
|
|
||||||
.map_err(|gix| git::fetch::Error::Prepare(gix.to_string()))?
|
|
||||||
.receive(gix::progress::Discard, &AtomicBool::default())
|
|
||||||
.map_err(|gix| git::fetch::Error::Receive(gix.to_string()))?;
|
|
||||||
info!("Fetch okay");
|
info!("Fetch okay");
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: (#72) reimplement using `gix`
|
|
||||||
#[cfg(not(tarpaulin_include))] // would require writing to external service
|
#[cfg(not(tarpaulin_include))] // would require writing to external service
|
||||||
#[tracing::instrument(skip_all)]
|
#[tracing::instrument(skip_all)]
|
||||||
fn push(
|
fn push(
|
||||||
|
|
|
@ -94,7 +94,7 @@ impl git::repository::OpenRepositoryLike for TestOpenRepository {
|
||||||
self.real.find_default_remote(direction)
|
self.real.find_default_remote(direction)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fetch(&self) -> Result<(), git::fetch::Error> {
|
fn fetch(&self, _repo_details: &git::RepoDetails) -> Result<(), git::fetch::Error> {
|
||||||
let i: usize = *self
|
let i: usize = *self
|
||||||
.fetch_counter
|
.fetch_counter
|
||||||
.read()
|
.read()
|
||||||
|
|
|
@ -9,5 +9,5 @@ fn should_fetch_from_repo() {
|
||||||
let gitdir = GitDir::new(cwd.join("../.."), StoragePathType::External);
|
let gitdir = GitDir::new(cwd.join("../.."), StoragePathType::External);
|
||||||
let repo_details = given::repo_details(&given::a_filesystem()).with_gitdir(gitdir);
|
let repo_details = given::repo_details(&given::a_filesystem()).with_gitdir(gitdir);
|
||||||
let_assert!(Ok(repo) = crate::git::repository::factory::real().open(&repo_details));
|
let_assert!(Ok(repo) = crate::git::repository::factory::real().open(&repo_details));
|
||||||
let_assert!(Ok(()) = repo.fetch());
|
let_assert!(Ok(()) = repo.fetch(&repo_details));
|
||||||
}
|
}
|
||||||
|
|
|
@ -125,7 +125,7 @@ mod push {
|
||||||
.expect_fetch()
|
.expect_fetch()
|
||||||
.times(1)
|
.times(1)
|
||||||
.in_sequence(&mut seq)
|
.in_sequence(&mut seq)
|
||||||
.returning(|| Ok(()));
|
.returning(|_| Ok(()));
|
||||||
open_repository
|
open_repository
|
||||||
.expect_push()
|
.expect_push()
|
||||||
.times(1)
|
.times(1)
|
||||||
|
|
|
@ -33,7 +33,7 @@ pub fn validate(
|
||||||
let next_branch = repo_config.branches().next();
|
let next_branch = repo_config.branches().next();
|
||||||
let dev_branch = repo_config.branches().dev();
|
let dev_branch = repo_config.branches().dev();
|
||||||
// Collect Commit Histories for `main`, `next` and `dev` branches
|
// Collect Commit Histories for `main`, `next` and `dev` branches
|
||||||
open_repository.fetch()?;
|
open_repository.fetch(repo_details)?;
|
||||||
let git_log = git::graph::log(repo_details);
|
let git_log = git::graph::log(repo_details);
|
||||||
|
|
||||||
let commit_histories = get_commit_histories(open_repository, repo_config)?;
|
let commit_histories = get_commit_histories(open_repository, repo_config)?;
|
||||||
|
|
|
@ -64,7 +64,7 @@ mod positions {
|
||||||
let mut mock_open_repository = git::repository::open::mock();
|
let mut mock_open_repository = git::repository::open::mock();
|
||||||
mock_open_repository
|
mock_open_repository
|
||||||
.expect_fetch()
|
.expect_fetch()
|
||||||
.return_once(|| Err(git::fetch::Error::TestFailureExpected));
|
.return_once(|_| Err(git::fetch::Error::TestFailureExpected));
|
||||||
let mut repository_factory = git::repository::factory::mock();
|
let mut repository_factory = git::repository::factory::mock();
|
||||||
repository_factory
|
repository_factory
|
||||||
.expect_open()
|
.expect_open()
|
||||||
|
@ -93,7 +93,7 @@ mod positions {
|
||||||
let repo_config = given::a_repo_config();
|
let repo_config = given::a_repo_config();
|
||||||
let main_branch = repo_config.branches().main();
|
let main_branch = repo_config.branches().main();
|
||||||
let mut mock_open_repository = git::repository::open::mock();
|
let mut mock_open_repository = git::repository::open::mock();
|
||||||
mock_open_repository.expect_fetch().return_once(|| Ok(()));
|
mock_open_repository.expect_fetch().return_once(|_| Ok(()));
|
||||||
mock_open_repository
|
mock_open_repository
|
||||||
.expect_commit_log()
|
.expect_commit_log()
|
||||||
.returning(move |branch_name, _| {
|
.returning(move |branch_name, _| {
|
||||||
|
@ -132,7 +132,7 @@ mod positions {
|
||||||
let repo_config = given::a_repo_config();
|
let repo_config = given::a_repo_config();
|
||||||
let next_branch = repo_config.branches().next();
|
let next_branch = repo_config.branches().next();
|
||||||
let mut mock_open_repository = git::repository::open::mock();
|
let mut mock_open_repository = git::repository::open::mock();
|
||||||
mock_open_repository.expect_fetch().return_once(|| Ok(()));
|
mock_open_repository.expect_fetch().return_once(|_| Ok(()));
|
||||||
mock_open_repository
|
mock_open_repository
|
||||||
.expect_commit_log()
|
.expect_commit_log()
|
||||||
.returning(move |branch_name, _| {
|
.returning(move |branch_name, _| {
|
||||||
|
@ -171,7 +171,7 @@ mod positions {
|
||||||
let repo_config = given::a_repo_config();
|
let repo_config = given::a_repo_config();
|
||||||
let dev_branch = repo_config.branches().dev();
|
let dev_branch = repo_config.branches().dev();
|
||||||
let mut mock_open_repository = git::repository::open::mock();
|
let mut mock_open_repository = git::repository::open::mock();
|
||||||
mock_open_repository.expect_fetch().return_once(|| Ok(()));
|
mock_open_repository.expect_fetch().return_once(|_| Ok(()));
|
||||||
mock_open_repository
|
mock_open_repository
|
||||||
.expect_commit_log()
|
.expect_commit_log()
|
||||||
.returning(move |branch_name, _| {
|
.returning(move |branch_name, _| {
|
||||||
|
|
Loading…
Reference in a new issue